存算分离实践:JuiceFS 在中国电信日均 PB 级数据场景的应用
01- 大数据运营的挑战 & 升级思考
大数据运营面临的挑战
中国电信大数据集群每日数据量庞大,单个业务单日量级可达到 PB 级别,且存在大量过期数据(冷数据)、冗余数据,存储压力大;每个省公司都有自己的集群,以及多个收集全国各省级业务信息的集团大数据集群,导致数据分散冗余,省集群与集团集群数据无法共享,跨地域任务延迟高。
电信早在 2012 年就开始创建各种集群,内部集群由各个厂商或其他内部团队部署,承载的业务由各个厂商运营,运维团队也是由各个厂商提供,因此集群涉及的版本非常多,包括 Apache、CDH、HDP 等多个版本。随着集群规模的不断膨胀,运维压力越来越大,定位和修复问题都需要依靠厂商,这并不是一种可持续发展的道路。
为解决现网痛点,强化集群安全,聚焦降本增效,满足内外部支撑需求,2021 年,中国电信组建了 PaaS 自研团队。在两年中,PaaS 团队针对现有的集群进行了优化,保证上万台机器的现有集群平稳运行。
在 2022 年初,PaaS 团队开始自主研发 TDP(TelecomDataPlatform)大数据平台,逐步替换现有集群,推进产品化。2022 年上半年,通过 Hadoop 2 版本的 TDP 底座部署了两大新集群,开始用于生产业务。2022 年下半年研发了 Hadoop 3 版本的 TDP 底座,开始面对如何使用自研底座升级现网大量的 Hadoop 2 集群的问题。
集群升级思考
在升级集群的过程中,希望新的集群设计可以解决现有痛点,具备业界先进的特性,并且为后续的技术迭代做好前置准备。
以下是我们在集群升级的过程中希望可以解决的问题:
拆分为小集群
我们计划将大集群拆分为小集群,原因如下:
从机器资源层面来说,无法同时使用几千台机器进行原有业务的迁移。此外,针对部分非常重要、对 SLA 的保证要求很高的业务,无法在生产环境直接从 Hadoop 2 原地升级到 Hadoop 3。
每个集群中都有许多不同的业务,将大集群拆分为小集群后可以按照业务进行划分,尽量减少它们之间的影响,降低业务迁移的压力和风险。拆分成小集群后也可以改善一些任务可能引起的整个集群不稳定的问题,更好地控制稳定性。
举个例子:有些机器学习的任务,并没有使用 Sark、Machine Learning 这样的方式去编写,而是直接在自己的程序中调用 Python 库。这个操作没有限制线程的使用。这样即使任务只申请了 2 核 10G 的内存,实际上也可能把这台机器的负载打到 100 以上。因此,拆分成小集群后,可以减少任务之间的互相影响,尤其是当平台上需要执行非常重要的任务时,在小节点的情况下,运维工作会相对容易。
此外,拆分集群还可以避免 Namenode 和 Hive 元数据的膨胀,降低整体的运维压力。因此,在业务允许的情况下,计划采用大集群拆分成小集群的方式进行升级。
升级过程尽量平滑
拆分小集群的过程中涉及到数据和计算两个维度,数据的迁移需要大量时间,如果业务复杂,计算也可能需要花费很长时间。因此,需要想办法将数据和计算的迁移分开,尽量扩大这两个集群之间的并行时间。
多集群之间的数据互访问题
当大集群拆分成小集群之后,需要考虑多个集群之间如何做数据互访。同时,在内部系统中有上万台机器和海量的数据,一直面临着不同类型的数据搬迁、冗余以及冷热数据的问题。
大数据、AI 结合需求
我们的 PaaS 平台正在逐步承接各种 AI 需求,其中最大的需求之一是非结构化数据的存储。将这部分需求与现有的结构化和半结构化数据存储集成在一起,这也是业界的一个前沿方向。
降本增效
将大集群拆分成小集群后,资源实际上会更紧张,由于不同集群的使用情况不同,某些集群可能只在假期、周末或进行日批量计算时才会被使用,因此需要确保闲置资源得到充分利用。
我们现有的所有机器都是高性能机器,拥有非常高的存储、内存和 CPU 性能。在未来的采购中,是否所有业务都需要采购这种高性能的机器呢?例如,对于小集群,是否可以快速搭建集群并省去部分存储和计算资源的成本?此外,在整个 Hadoop 2 升级到 Hadoop 3 的过程中,EC 技术可以省去 50% 的存储资源,希望能够将整体存储费用降到更低。
基于上述思考,总结出以下四个策略:
? 存算分离:将存储和计算分离。
? 对象存储:使用对象存储来解决结构化、非结构化和半结构化数据的存储问题。
? 弹性计算:采用弹性计算技术来解决拆分小集群后集群资源不充分利用的问题。
? 容器化:采用容器化技术来解决深度学习计算任务和资源管理的问题,从而实现更高效地降本增效。
02- 存算分离架构设计& 及建设历程
存算分离-组件选型
早期大数据架构是基于 Hadoop 2.0 的存储计算一体化集群,计算和存储均使用高性能机器。而现在的架构则是存储计算分离,将更多的磁盘用于对象存储,建立了一个对象存储池,以及相应的元数据加速层,所有的HDFS访问都会通过元数据加速层访问底层的对象存储层。
存算分离技术选型
对象存储
在考虑不同的对象存储方案时,主要对比了 Minio、Ceph 和 Curve,而云上的对象存储并不在的考虑范围之内。在这三种选择中,最终选择了业界使用最广泛、支持各种 K8S 容器、S3 以及底层块存储的 Ceph。
对接 HDFS
存算分离的主要目标是将对象存储与 HDFS 打通。在自研的 Hadoop 2 和 Hadoop 3 中都涉及了这项工作,最初是采用亚马逊提交的 S3 代码,国内的阿里云、腾讯云和华为云也分别推出了自己的实现并提交到 Hadoop 社区中,但这些方案缺乏对元数据的加速支持。
近年来,元数据加速和数据缓存技术逐渐成熟。这些技术旨在解决存算分离后,Yarn 底层数据无法与本地数据进行亲和的问题。在这次打通中,不仅希望将对象存储与 HDFS 直接打通,还希望达到业界领先的性能水平。
对象存储可以通过多种方式与 HDFS 对接,例如使用 Hadoop 原生接口、Ceph 的 CephFileSystem 或 JuiceFS 等开源产品。云厂商也提供了类似的解决方案,例如阿里云的 Jindo 和腾讯云的 GooseFS。这些产品都提供了元数据加速和缓存功能。
虽然云厂商的产品具有成熟性和规模优势,但无法获取它们的源代码,并且它们需要与云厂商提供的云上资源绑定。因此,我们选择了开源的 JuiceFS。JuiceFS 目前是最成熟的开源解决方案,社区活跃度很高。能够适配 Hadoop 商业版本如 CDH 和 HDP。最终,决定了 Hadoop 3+JuiceFS+TiKV+Ceph 的组合作为我们的存算分离方案。
存算分离架构带来的价值
-
单个集群存储的数据变少,元数据压力变小
经过计算存储解耦,存储和计算可以独立进行弹性扩缩容,并实现数据的统一存储和跨计算集群共享。这种方式可以显著降低单个集群内的存储数据量,减轻整体元数据的压力。 -
解决元数据瓶颈以及单点性能问题
元数据可水平扩展,无单点性能瓶颈:元数据的压力反而会在元数据加速层这一层来承担,并且可以做到水平的扩展,解决了原来的元数据的瓶颈和单点的性能的问题。 -
解决 Ceph 层联邦不均衡问题
Ceph 层之前集群里出现了很多的联邦不均衡的问题,比如某一个业务在使用了 namespace3(ns3),会使它的数据都存在 ns3 上面,导致 ns3 和其他的联邦整体数据、压力不均衡。 -
解决整体扩容时的瓶颈问题
在新的集群里通过纠删码去降低存储成本,然后通过对象存储的水平扩展,让集群的扩展的能力变得更好。
存算分离项目实践:流量轨迹项目迁移
流量轨迹的数据主要是 DPI 数据,它是用户上网的各种各样的流量数据,包括 3G、4G 和 5G 数据。电信客服可以通过一个展示页面查到用户在历史的一段时间里流量消耗是否跟费用扣款一致。
随着 5G 用户的增多,现有的集群需要不断填充 5G 流量数据,导致存储压力不断增加。所有的数据都是通过采集系统从 31 个省采集而来,现在的数据量已经达到 PB 级别,并且整体规模还在不断增长,每天处理的数据量约为 800-900TB。这是一个比较简单的业务场景,但是挑战在于面临的数据量级太大了。
之所以选择这个业务场景进行迁移,是因为这个的场景的 SLA 要并不是那么高,它本身是小时级的,如果宕机一个小时,影响相对较小。
由于面临的数据量太大,选择了执行小时级别的批处理任务。通过耗费大量的资源来处理整体的计算量,以便统计用户每小时的流量消耗及其分布情况,并将这些数据存储到 HBase 和 Hive 中。
基于现有采集系统的数据,将所有数据上传到 Hadoop2 集群中。迁移需要打通 Hadoop2 集群和对象存储之间的连接,JuiceFS 在这个过程中发挥了关键作用。有了 JuiceFS,无需重启 Yarn 和 HDFS 等核心组件服务,就可以将对象存储挂载上去。当新的数据进来时,当天的采集系统就可以将其写入对象存储中。计算任务则可以直接从对象存储中读取数据,对于原有任务来说,只需修改路径,其他事项均不需要变化。
项目迁移实践
在存算分离的上线过程中,迭代速度非常快,仅用了两个月时间就完成了整个项目的落地。JuiceFS 的易用性,是能够让我们在巨大压力下按时保量解决问题的重要前提。同时,在实践中,JuiceFS 在解决一些关键问题方面也发挥了非常重要的作用。
第一:PB 级的支撑能力
- 解决元数据存储和连接压力
在之前的 JuiceFS 测试中,选择使用 Redis 作为元数据引擎,数据存储在 Redis 中,整体性能非常好。但是,随着搭建了几百台机器,每个节点启动 Yarn 任务时,每个容器都会访问元数据,导致 Redis 崩溃。因此,将其替换为 TiKV。
- 时间戳写竞争压力
在众多集群中,即使时间窗口是保持一致的,由于机器规模非常庞大,仍然可能出现时间冲突和竞争的问题。为了解决这个问题,添加了一些补丁来优化时间和竞争,放宽了相应的一些参数配置。
- 垃圾清理速度瓶颈
我们发现 Ceph 存储的数据量越来越高,并没有完全释放下去,主要是因为 DPI 的业务数据量非常大,只会去存几天的数据,所以每天都会去写入 PB 级数据,然后消费 PB 级数据,以及删除PB级数据。
- 回收站清理线程泄露问题
在部署监控后发现,有些特定时间点会出现 TiKV 和 Ceph的稳定性问题。经过排查,发现问题出现在客户端回收站线程泄露上。
第二:在高负载下提升性能
流量轨迹项目试点时,为了满足 32TB 计算和 10PB 存储的需求 ,选择了一部分性能较好的机器。然而,在评估 Ceph 的时候,没有考虑到 Ceph 所使用的内存和 CPU 资源,导致每台机器的吞吐量、网络带宽和磁盘带宽基本上都已经打满了,处于类似于压力测试一样的环境。在这种高负载的环境下,不得不对 Ceph 进行调整以解决内存溢出导致的宕机问题,并优化适配 JuiceFS 以加速 Ceph 的数据删除和写入性能。
项目规划
计划在 2023 年的 Hadoop 3 升级中实现以下规划:
在底层,将完全依赖 JuiceFS 来储存和加速元数据,并根据不同业务将对象存储拆分成不同池或集群。
在计算资源层,每个集群都会有自己的计算资源池,但我们将添加一个弹性资源池,用于多个资源池之间的调度。
在统一访问层,将提供一套统一的管理工具,任务的提交都将通过任务网关,并通过元数据打通多个集群。还将把集群划分为不同的 Pod 或集群,例如 DPI 集群、位置集群和纹理集群等,某些集群也可以将热数据存储到自己的 HDFS 中,并通过数据库和 MPP 来提高性能。
另外,还将提供一套统一的集群管理工具,包括存储画像、任务画像、集群日志采集和日志大盘等,以便更好地监控和管理集群。
总之,希望通过按小集群划分、存算分离等方式来提高性能,通过 JuiceFS 加速元数据并弹性调度计算资源,最终通过统一的管理工具来简化运维流程。
03- 运维经验分享
如何使用高性能机器进行混合部署
原则上在集群规划时不要有异构机型,尽可能选择同种类型的机器。这样可以保证 vcore 和 mem 保持恒定的配比。但由于公司内部对于机器的申请非常谨慎,因此流量轨迹项目实际上只拿到了 180 台左右的旧的高性能机器进行替换,这些机器虽然性能高,但并不适合作为大量计算或存储的机器。为了充分利用这些资源,使用存量机器混合部署,解决了规划方面的问题。
共提供 10PB 存储,8100(45C180)Vcore、 32TB(180G180)计算资源,其中,Ceph 使用了48G(4G*12)的计算资源,其他的都属于 Yarn。
机器 CPU 内存规划不合理
在规划时期 Ceph 占用的 CPU、内存没有考虑,导致机器内存耗尽、机器负载持续偏高造成服务器宕机,引发任务失败。Ceph 节点与 Hadoop 集群共用一块网卡,节点宕机触发 OSD 数据迁移,计算任务 Shuffle 与数据迁移打满网卡,经过实践优化配置:
? 所有节点:需两块 SSD Raid1 方式做根盘,以此来提高稳定性。
? 计算节点:建议 CPU 线程数:内存 为 1:4 | 1:5 左右,混合部署预留出 Ceph 占用资源
? 存储节点:单个 OSD(单块盘)建议分配 6GB 内存,高性能服务器建议使用双网络平面;如果条件允许,建议将内外网分开,将 Ceph 内部的数据同步和外部的访问分开,这是一种更加理想的状态
? 元数据节点:建议高性能 NVME 磁盘 这是与 PingCAP 做了多次沟通后得出的结论,磁盘的负载包括 TiKV 在当前 180 台计算高频的使用下,压力很大,到 70%~80% 的情况。
? Ceph节点操作系统:CentOS-Stream-8
? 其他节点操作系统:CentOS-7.6+、CentOS-Stream-8
NodeManager 本地目录不合理
在高负载、PB 级别的情况下,任务需要大量的磁盘空间,因此将几乎所有的磁盘空间都分配给了 Ceph,而 HDFS 只有一块机械硬盘。然而,在任务高峰期,由于中间数据需要写入到这块机械硬盘中,导致磁盘 IO 延迟过高,最终成为了任务执行的瓶颈。
经过优化,在机器的受限的条件下,把 Yarn 本地目录配置到根盘(SSD),数据盘全部分配给 OSD,解决磁盘带来的性能问题。
JuiceFS 上报指标关闭
为了减轻 JuiceFS 的负载,关闭了 Pushgateway 所有的监控指标。因为监控指标需要通过容器持续上报,如果 Pushgateway 响应时间过长,就会导致 HDFS 的回调一直卡住,从而无法结束任务。虽然这样做无法查看一些基础的统计指标,但希望后续能够通过其他方式来展示 JuiceFS 的监控指标。
Redis 连接数限制问题
使用 Redis 作为元数据引擎时,连接数与 Yarn 容器的数量成正相关。当数据量过大,任务过多时,Redis的最大连接数上限(4K)瞬间就被打满。因此,在处理冷数据时使用 Redis 或关系型数据库,在高性能计算方面则建议使用 TiKV(数据盘使用 NVMe)。目前正使用 TiKV,它能够支持大约 10 万个并行连接数。
Tikv 6 小时周期性繁忙
之前曾遇到一个困扰很久的问题,使用 TiKV 时会出现 6 小时的周期性 Busy。通过日志分析,发现 JuiceFS 开启了大量的日志清除线程。首先试图关闭 TiKV 的上报机制来解决,但是发现这个问题仍然存在。
通过研究发现,JuiceFS 存在一个线程溢出 bug,导致每个 nodemanager 开启了上万个日志清除线程。每个线程在调用文件系统时都会触发一个清除操作。每到 8 点整点,这些线程同时执行清除操作,压垮了 TiKV,导致高峰期出现非常高的尖峰。
因此,在选择存储垃圾回收机制时,需要取舍 HDFS 和 JuiceFS 两种机制。尽管两种机制都可选,但更倾向于关闭 HDFS 的垃圾回收机制,让 JuiceFS 独自负责整体的垃圾回收。
JuiceFS 删除慢
JuiceFS 的垃圾回收功能需要进行文件删除操作。在最初使用 JuiceFS 时,发现即使调整了 Ceph 的相应参数,将删除和写入权重调整到了最高,每天也无法删完 PB 级的数据。
删除性能很低,需要使用多线程的方式来进行删除,但 JuiceFS 的每次删除操作都需要客户端上报指标,然后客户端检测回收站中哪些文件需要删除。如果删除的数量很大,无法使用客户端进行处理。最终,JuiceFS 社区提供了一个解决方案和相应的补丁,可以修复多线程问题并满足 PB 级别的删除需求。将其挂载到了固定的几台服务器上进行删除,并将线程数调整到了最高。目前,这个补丁还没有被合并到正式版中,但预计它将在未来被合并。
JuiceFS 写冲突
JuiceFS 存在写冲突的问题,已通过调大父文件夹更新修改时间的时间间隔,降低频繁的文件属性改写来进进行缓解,但是还没有根本的解决。目前团队在积极地和 JuiceFS 团队一起探讨这个问题,计划在JuiceFS 的 1.0.4 版本修复这个问题。
04- 后续计划
? 部署更大规模存算分离集群
? 探索不同集群与对象存储池之间的打通
? 探索单集群访问多对象存储集群
? 探索存算分离和数据湖的结合
? 构建结构化非结构化统一存储池
长期来看,希望存算分离产品能够在内部的上万台机器的升级过程中发挥更好的作用,并在各种场景下得到验证;解决 Ceph 扩容带来的集群稳定性问题、支持 Kerberos、Range 提升安全性,提升超大规模性能,继续提高产品的稳定性、安全性和易用性;也会进一步探索云原生的发展。
最后,中国电信期望与 JuiceFS 社区和各位专家持续交流和解决问题,非常希望社区的各位专家可以加入电信,一起来构建 TDP 产品。也欢迎大家试用 TDP 产品。
如有帮助的话欢迎关注我们项目 Juicedata/JuiceFS 哟! (0?0?)