2020 年初,随着网易互娱的海外业务增长与海外数据合规的需求,我们开始了网易互娱大数据离线计算平台迁移出海的工作。前期,我们采取了云主机裸机加上高性能 EBS 块存储的方案。但是,这个方案存储费用高昂,成本是国内自建机房的数十倍。
于是,我们决定在公有云上构建一个平台,这个平台不仅需要更加适应当前业务场景、与历史业务更为兼容,还要比公有云的 EMR 托管方案更为经济。我们主要从存储、计算和数据分层生命周期管理三方面进行了成本优化,具体的优化方案将在下文为大家详细介绍。
最终,这个项目给下游数据业务和分析部门提供了完整 Hadoop 的兼容性,避免了所有业务逻辑推倒重来;给游戏数据业务出海节省了大量成本,存储成本为优化前的 50%,算力总成本为优化前的 40%,冷数据成本为优化后线上存储成本的 33%。未来随着业务量的增加,成本节约按 10 倍比例节约相应的费用,为出海后的数据化运营等提供有力支持。
01. 大数据平台海外上云方案设计
在 2020 年,我们开始了一项紧急的出海任务。在国内,我们的业务一直以自建集群的方式进行部署和运行。为了在海外能够快速上线,我们紧急上线了一个与国内集群完全相同的解决方案,采用了物理节点构建的一套存算一体的系统。我们选用了裸金属服务器 M5.metal,并使用 EBS gp3 作为存储。
这套方案的缺点是成本非常高昂,但是它的好处是解决了一个非常痛苦的问题,即我们需要兼容所有历史业务,确保所有历史业务能够快速、立即地在海外运行。我们的上下游业务可以无缝迁移到海外,并支持每天接近30万个作业的调度。
但是,成本一直是一个不能忽视的问题。因此,我们需要重新选择方案,以获得性能更优、成本更低的解决方案,并确保兼容性。根据业务需求和大数据场景的特点,我们从以下几个方向评估如何进行方案选择:
- 以时间/空间换性能;
- 基于业务场景的实现部署优化;
- 加入中间件实现兼容性的整合;
- 充分利用云资源的特性优化成本。
Hadoop 上云
一般 Hadoop 上云有下面两种方案,EMR+EMRFS、Dataproc+GCS。这两种方案就是一个正常出海的姿势。或者使用一些云原生的平台,例如 BigQuery、Snowflake,Redshift 等做数据查询方案,但是我们没有去用这些方案。
为什么没有使用 EMR
因为我们所有的业务都非常依赖 Hadoop,我们目前使用的 Hadoop 版本是根据业务需求定制的内部版本,并实现了各种新版本功能向下兼容,有很多内部的需求和优化在 EMR 的 Hadoop 版本未能覆盖。至于云原生的 BigQuery 等方案对业务来说,是一个改动更大更遥远的方向。
为什么没有直接使用 S3 存储
- 由于对数据业务安全的高需求导致我们有复杂的业务权限设计,远超亚马逊 IAM(Identity and Access Management)ROLE 能够实现的上限。
- S3 的性能受限,需要分桶和随机目录等优化措施,对业务使用不透明,调整目录 prefix 去适配 S3 分区或使用更多的桶的方案都需要业务调整已有的使用方法,无法适配我们目前的目录设计。另外,作为对象存储实现的文件系统,直接对 S3 的目录进行 list 和 du 等操作在超大文件数据情况下,基本上是不可用的,但是这又恰好是大数据场景下大量使用的操作。
存储选型:HDFS vs 对象存储 vs JuiceFS
我们主要从以下这些维度来评估存储组件。
业务兼容性:对于我们这种拥有大量存量业务需要出海的情况,兼容性是一个非常关键的考虑因素。其次,降本增效不仅仅指降低存储成本,还包括资源成本和人力成本的考虑。兼容性方面,JuiceFS 社区版兼容 Hadoop 生态,但需要在用户端部署 JuiceFS Hadoop SDK。
一致性:在当时,我们对 S3 进行了调研,但在 2020 年第一季度之前,并没有实现强一致性,而目前也并非所有平台都能做到强一致性。
容量管理:对于我们当前自建的集群,有一个重要的问题是需要预留资源。也就是说,我们不可能使用到 100% 的资源,因此按需使用是一个非常节省成本的方向。
性能:基于 HDFS 可以达到我们国内自建的 HDFS 的性能水平。我们国内提供给业务的 SLA 是在单集群下 4 万 QPS 的情况下,能够实现 p90 在 10 毫秒以内的 RPC 性能。但是对于类似 S3 的情况,实现这样的性能非常困难。
权限认证:在自建集群中,使用 Kerberos 和 Ranger 做认证和权限管理。但 S3 当时并不支持。JuiceFS 社区版本同样也不支持。
数据可靠性:HDFS 使用三副本来确保数据可靠性。当时我们测试时 JuiceFS 元数据引擎使用的是 Redis。我们发现,在高可用模式下,如果发生主节点切换,存储会出现卡顿,这对我们来说是很难接受的。所以我们采用在每台机器上独立部署 Redis 元数据服务的方式,细节将在下文展开。
成本:块设备这样的方案成本很高。我们的目标是要使用 S3,如果每个人都只使用 S3,成本当然是最低的。如果使用 JuiceFS,后面的架构会有一定的额外成本,因此我们后面会解释为什么它的成本不是最低的。
02. Hadoop 海外多云迁移方案
存储层存算分离: Hadoop+JuiceFS+S3
JuiceFS 与 Hadoop 的结合可以降低业务的兼容的成本,快速实现已有的业务出海。许多用户在使用 JuiceFS 方案时,是通过 SDK 加上 Hadoop 开源版本来实现的。但这样使用会有一个权限认证的问题,JuiceFS 社区版不支持 Ranger 和 Kerberos 的权限认证。因此,我们还是使用了 Hadoop 的整个框架。维护成本看上去很高,但在国内我们有一套自建的组件在维护着,所以对我们来说差不多没有成本。如下图所示,我们使用 Fuse 将 JuiceFS 挂载到 Hadoop,再使用 S3 存储。
先简单对比我们与基于 EBS 自建单集群的性能。
- 在 4 万 QPS 的情况下可以达到 p90 10ms;
- 单节点能够承受 30000 IOPS。
一开始我们上云时采用了 HDD 模式,具体来说就是 st1 存储类型。但很快我们发现,当节点数量较少时,实际的 IOPS 远远不能满足我们的要求。因此,我们决定将所有的st1存储类型全部升级到 gp3。
每块 gp3 默认提供大约 3000 个 IOPS。为了提升性能,我们挂载了 10 块 gp3 存储卷,总共实现了 30000 IOPS 的性能。这个改进让我们的系统可以更好地满足 IOPS 的需求,不再受限于节点数量较少时的性能瓶颈。gp3 的高性能和灵活性使得它成为我们解决 IOPS 问题的理想选择。
每个节点目前的默认带宽是 10Gb。但是不同的机型带宽也有所不同。我们取了一个基准,即 30000 个 IOPS 单节点,带宽为 10Gb。我们的目标是要能够整合我们的 S3 存储,即在高性能的同时也要考虑存储的成本,数据最终会落在 S3 上面。
而最重要的是要兼容 Hadoop 访问,也就是所有的业务其实都不需要做任何修改,可以直接上云解决兼容性问题。对于一些历史业务来说,它可能有一定的业务价值,但是我们要评估业务的改造成本和平台兼容的成本,在我们场景业务中重构所有历史业务的人力成本当前是大于平台兼容成本,而且不可能短时间完成。
我们对 JuiceFS 的挂载方式与官网可能有所不同。我们在每台机器上都部署了本地的 JuiceFS 和 Redis(如下图所示)。这样做是为了最大化 JuiceFS 的性能,并将本地元数据的损耗降到最低。我们曾尝试过使用 Redis 集群和 TiDB 集群,但发现元数据性能差了好几个数量级。因此,我们一开始就决定采用本地的部署方式。
另一个好处是我们的系统与 DNO(Data Node Object)绑定。我们可以控制每个 DNO 的文件数量,即单个节点的文件数量,使其稳定在一个合理的水平范围内。例如,我们一个 DNO 大约有 3 百万到 8 百万个元数据文件的上限,所以元数据单节点大约为 20GB。这样,我们不需要过于关注其膨胀情况,将一个大规模的分布式 Redis 需求转化为单节点元数据可控的 Redis 需求。但稳定性也是一个问题,如果单节点出现稳定性问题,我们就会面临丢失的风险。
为了解决单节点的宕机问题,我们与 DNO 进行了绑定,并利用了 HDFS 多副本机制,在我们集群有两种副本模式,一种是三副本,一种是 EC(Erasure Coding)副本。不同模式下,都通过副本的机制实现数据的高可靠性:在多副本的部署方案下,即使某个节点完全挂掉,我们也可以直接剔除它,而不影响整体运行和数据的可靠性。
在实践中,将单节点部署在本地,同时使用 JuiceFS 和单节点 Redis,是能够获得最佳性能的方式。因为我们需要与 HDFS 和 EBS 方案的性能进行对标。
我们通过基于 HDFS 的分布式水平扩展和 JuiceFS 的缓存与读写策略优化,实现了高性能的 HDFS。优化部分如下:
- 使用 JuiceFS 替换 gp3 的目录,以一块小的 gp3 存储作为 JuiceFS 的缓存目录,实现了 IOPS 对齐 gp3 的水平;
- 通过优化 JuiceFS 缓存机制,定制的异步删除,异步合并上传,S3 目录 TPS 预置等优化减少落到 S3 的情况,低成本存储的 S3 替换 gp3;
- 基于 HDFS 集群的分布式实现节点水平扩展;
- 利用 Hadoop 异构存储的特性,根据业务特性拆解 IO,以优化性能和成本。我们将 HDFS 存储拆分为两个部分,"DISK" 和 "SSD"。"SSD" 存储类型对应的是使用 JuiceFS 的 EBS 缓存与 S3 整合的混合存储。"DISK" 存储类型被配置为写入 DN 的 EBS 存储的目录。在那些会频繁覆写的目录,例如 Stage 目录,我们会将这些目录设置成使用 DISK 进行存储。EBS 存储更适合频繁擦写,对比 S3 的少了额外 OP 费用,而且这些目录对存储的总量要求是可控的,因此这个场景我们保留了一小部分 EBS 存储。
计算层:Spot 节点与按需节点混合部署方案
首先,当我们将国内自建的 YARN 集群迁移到云上时,它无法适应云上的资源特性以实现成本优化。因此,我们基于 YARN 的智能动态伸缩方案与标签调度相结合,同时采用 Spot 节点与按需节点混合部署方案,来优化计算资源的使用。
- 调整调度器策略为容量调度 (CapacityScheduler);
- 划分按需节点分区和 Spot 节点分区;
- 调整有状态的节点到按需节点的分区 ,让不同状态的任务跑在不同的区域;
- 使用按需节点兜底;
- 回收通知与 GracefulStop,当抢占节点在回收之前会提前收到回收的通知,调用与 6. GracefulStop 停止业务,避免与用户作业直接失败;
Spark+RSS,减少当节点回收的时候,数据本来在动态节点上面从而去导致要重算作业的概率。
- 基于我们的业务需求去做了一些动态智能伸缩的方案。和原生方案对比,我们更关注的方向是:基于业务的状态去做动态伸缩,因为云厂商不可能知道业务的热点时间。
- 基于内部运维工具 Smarttool 的周期性预测,实现智能伸缩。我们取前三周的一个历史数据,去做一次简单的拟合,然后通过 Smarttool 预置的算法得到拟合残差序列 resid,以及预测值 ymean。通过这个工具预测某一天某个时间点它的资源使用应该是什么样子,然后去实现动态伸缩容。
- 基于时间规则的定时伸缩,例如针对特定时间做预伸缩:每月 1 号的月报表生成时间、大促等特定的时间做提前的容量预置。
- 基于使用率的动态伸缩,使用容量在一定时间内大于阈值上限,或小于阈值的下限,会触发自动扩容和缩容,实现非预期的用量需求兜底。尽量保障我们的业务在云上面是能够得到一个稳定的,但是成本相对比较低的,计算资源的方案。
生命周期管理:数据分层,实现存储成本优化
我们实际上是基于副本机制将 JuiceFS 和 S3 整合的数据可靠性。不论是三副本还是 1.5 副本的 EC,都会有额外的存储支出成本,但是我们考虑到一些数据热度的情况,一旦数据过了一定的生命周期,其对 IO 的需求可能不再那么高。因此,我们引入了一层 Alluxio+S3 的单副本层,来处理这些数据。但是需要注意,如果不改变目录架构,这一层的性能其实比使用 JuiceFS 要差很多。尽管如此,在冷数据的场景下我们仍然可以接受这样的性能。
因此,我们自主开发了一个数据治理和组织分层的服务,通过对数据进行异步处理,实现了对不同生命周期数据的管理和成本优化。我们称这个服务为数据生命周期管理工具 BTS。
BTS 的设计基于我们的文件数据库、元数据以及审计日志数据,通过对表格及其热度的管理,来实现数据生命周期管理。用户可以使用上层的 DAYU Rulemanager 自定义规则以及使用数据的热度来生成规则。这些规则指定哪些数据被视为冷数据,哪些数据被视为热数据。
根据这些规则,我们会对数据执行压缩、合并、转换、归档、或删除等不同的生命周期管理操作,并将它们分发到调度器去执行。数据生命周期管理工具 BTS 提供了以下能力:
- 数据重组织,将小文件合并为大文件,优化 EC 存储的效率和 namenode 压力;
- 表存储和压缩方式的转换:异步将表从 Text 存储格式转换为 ORC 或 Parquet 存储格式,并将压缩方式从 None 或 Snappy 转换为 ZSTD,可以提高存储和性能效率。BTS 支持按分区进行异步表转换;
- 异构数据迁移,将数据异步在不同架构的存储之间迁移,为数据分层提供组织能力。
存储分层架构我们简单地分为三层:
- 性能最好的是 HDFS on JuiceFS(热),3 副本;
- 其次是 HDFS on JuiceFS EC 的模式(温热)1.5 副本;
- 再次是 Alluxio on S3(低频冷数据)1 副本;
- 在所有数据消亡之前,它们都会被归档到 Alluxio on S3 并变为单副本。
目前,数据生命周期治理效果如下:
- 60%冷, 30%温热, 10%热;
- 平均的副本数 (70% 1 + 20% 1.5 + 10% * 3) = 1.3 在归档这样对性能要求不高的场景,我们能够实现约 70%的数据。使用 EC 副本时,大约 20% 的数据,而使用三副本时约为 10%的。我们整体上控制了副本的数量,平均副本数维持在约 1.3 个。
03. 出海新架构的上线效果:性能与成本
在测试中,JuiceFS 在大文件的读写方面能够达到相当高的带宽。特别是在多线程模型下,大文件读取的带宽接近客户端的网卡带宽上限。
在小文件场景下,随机写入的 IOPS 性能较好(得益于 gp3 磁盘作为缓存),而随机读的 IOPS 性能相比之下较低,大约差了 5 倍。
EBS 方案与 JuiceFS+S3 方案在业务实测的对比,测试用例为我们生产环境下的业务 SQL, 可以看出 JuiceFS + S3 基本与 EBS 差别不大,部分 SQL 甚至更优。所以 JuiceFS + S3 能够替换掉全量 EBS 。
使用基于JuiceFS 的 S3+EBS 混合分层的存算分离方案替换原来的 EBS 方案,通过数据治理和数据分层,从原来的 Hadoop 三副本的机制下降到平均 1.3 个副本,节省 55% 的多副本成本,整体存储成本下降 72.5%。
通过智能动态伸缩实现了 85% 集群使用率和使用 95% 的 Spot 实例替换了按需节点,总体计算成本对比优化前优化超过 80%
04. 总结与展望:迈向云原生
相比原生的 JuiceFS 方案,Hadoop+JuiceFS 使用额外的副本实现了储性能优化和实现兼容性与高可用的支持。DN 只写一个副本的方案, 依赖 JuiceFS 在可靠性上的迭代优化。
虽然已经在不同云上实现一套多云兼容、对比 EMR 更好的方案,但是对于混合多云和云原生的方案还需要更多的迭代。
对于未来大数据云原生场景的展望,目前我们采取的解决方案并非终极版本,而是一个过渡性方案,旨在解决兼容性和成本问题。未来,我们计划采取以下措施:
- 推进业务向更云原生的方案迁移,实现 Hadoop 环境的解耦,并将数据湖和云上计算紧密结合在一体。
- 推动更高层次的混合多云计算和混合存储方案,实现真正的整合,而不仅仅是现在的兼容性。这将为上层业务部门带来更多的价值和灵活性。
希望这篇内容能够对你有一些帮助,如果有其他疑问欢迎加入 JuiceFS 社区与大家共同交流。