vivo Celeborn PB 级 Shuffle 优化处理实践
作者: vivo 互联网大数据团队-Wang Zhiwen、Cai Zuguang
vivo 大数据平台通过引入 RSS 服务来满足混部集群中间结果(shuffle 数据)临时落盘需求,在综合对比后选择了 Celeborn 组件,并在后续的应用实践过程中不断优化完善,本文将分享 vivo 在 Celeborn 实际应用过程中对遇到问题的分析和解决方案,用于帮助读者对相似问题进行参考。
1 分钟看图掌握核心观点👇
一、背景
近年来,随着 vivo 大数据平台的数据量和任务量持续快速增长,新增的计算机资源已无法满足不断扩大的存储和计算需求。同时,我们观察到互联网和算法等在线业务在白天流量高峰,而在夜间流量显著下降,导致部分服务器在低峰时段资源利用不充分。与此相对,离线业务的高峰期正好落在在线业务的低峰期间。
在此背景下,我们于 2023 年起与容器团队合作,启动了在离线混部项目,旨在探索将海量的大数据离线任务运行到 K8S 在线集群中。通过实现在线服务、大数据离线任务、与机器学习离线任务的混合部署,我们期望缓解计算资源的潮汐现象,实现资源的弹性伸缩和共享,增强大数据平台的资源供应,同时提升公司整体服务器的利用率并达到降本增效的目的。为实现上述混部效果我们对当前主流的方案 YARN on K8S 和 Spark on K8S 做了大量的调研,方案对比情况如下:
基于多方面因素综合考虑,我们团队决定采用 Spark on K8S 方案去支持在离线混部项目,为此我们急需一套成熟的 remote shuffle service 服务支持项目的推进。
二、RSS 初体验
2.1 百花齐放,只取一支
在 Spark 作业中,高效的 Shuffle 服务对性能至关重要。我们对主流 Shuffle 方案(Celeborn、Uber RemoteShuffleService、Firestorm)进行了深度调研。以下是我们 vivo 团队对主流 shuffle 服务的初步调研结论。
基于全面评估,我们团队初步选择 Celeborn 作为核心 Shuffle 解决方案。以下是我们选择 Celeborn 的关键决策因素:
生态兼容性:Celeborn 对 Spark 3.x(包括最新 Spark 版本)的 Dynamic Allocation 原生支持,优于 Uber RSS 的有限兼容(仅 Spark2.4/3.0)和 Firestorm 的不支持 Spark 3.2。符合 vivo 当前使用的 spark 版本,避免未来 Spark 兼容带来的风险。
可观测性与运维友好性:Celeborn 的完整指标系统(集成 Prometheus)提供了端到端监控能力,可在运维过程中实时识别瓶颈。而 Uber RSS 的监控缺失和 Firestorm 无指标问题,将显著增加生产环境故障排查难度。
性能与稳定性保障:Celeborn 使用 Off-Heap 内存机制大幅减少 JVM 垃圾回收的 STW 停顿,提升吞吐量。同时采用 Slot 并发控制避免 Worker 过载,预防资源争抢导致的作业失败。Firestorm 虽优化文件格式,但不支持最新 Spark 版本;Uber RSS 缺乏并发管理能力。
劣势的可行性规避:Celeborn 不支持 DFS 的情况,在当前架构下可接受,未来开源社区正推进 DFS 支持,技术债可控。
基于上述的全面评估,Celeborn 在兼容性、可靠性、可观测性三方面脱颖而出,是平衡长期演进与短期落地的最优解。
2.2 精心培养,绽放异彩
2.2.1 硬件适配:机型选择与性能调优
我们选取了三类线上常见且服务时间较长的服务器进行测试,充分利用现有硬件资源,验证 Celeborn 在不同配置下的性能表现:
通过对比发现,机型 B 表现出最佳的综合性能,而机型 C 虽然单盘性能出色(SSD 达 1.6GB/s),但受限于 RAID5 配置和较小容量,在持续写入场景反而出现数据挤压,这提示我们 Celeborn 对磁盘数量比单盘性能更敏感。基于测试结果,我们总结出 Celeborn 的硬件选择原则:
优先考虑磁盘数量:多块 HDD 的聚合带宽往往优于少量高性能 SSD
避免过度 RAID 化:shuffle 数据一般为临时数据,即使有少量丢数对离线业务影响也不大,无需做 raid
内存适度配置:Celeborn 对内存需求并非线性增长,250G 左右已能满足 PB 级 Shuffle 需求
利用过保或服务较久的老旧机型:Celeborn 对硬件要求相对宽容,是消化老旧服务器的理想场景
这些结论帮助我们优化了硬件选择策略,将 Celeborn 集群部署在性价比最优的机型 B 配置上,实现了资源利用的最大化。
2.2.2 服务健壮性:高可用与运维验证
作为关键基础设施,Celeborn 的服务稳定性和运维友好性是我们评估的重点。我们设计了多场景的故障模拟测试,验证其生产级可靠性。
Master 高可用测试
Celeborn 采用 Raft 协议实现 Master 高可用,其高可用的能力是我们验证的重中之重,为此我们模拟线上的日常操作对 master 进行测试验证得出以下结论:
无脏数据情况下,Master 节点轮流重启不影响运行中任务
整个过程中 Shuffle 服务零中断
三 Master 架构下,即使两个节点同时故障,只要一个存活就不影响任务运行
在整个测试中我们发现在 k8s 环境下 Worker 重启会带来 IP 的变动,若有频繁的重启会在 Master 产生脏数据,当 Master 触发重启操作时恢复会非常慢。为此我们在 k8s 环境上都固定了 Worker 的 IP,让 Worker 的变动不影响 master。
服务热更新验证
版本变更是生产环境常态,我们测试了不同副本配置下的更新影响:
测试表明,双副本模式是生产环境的必选项,虽然节点下线需要更长时间等待数据传输完成,但保证了服务连续性。
2.2.3 性能测试
在性能方面我们对 RSS 的要求是不明显低于 ESS,为此我们在 3master+5slave 的集群下做了对比验证,测试数据如下:
结果呈现三个显著趋势:
全面加速:在小规模数据量(5.9TB)场景,Celeborn 耗时仅为 ESS 的 47%,优势明显
稳定优势:随着数据量增大,Celeborn 始终快于 ESS,28.3TB 时仍有 20%提升
可靠性差异:ESS 在 79.3T 及以上 Shuffle 量时完全失败,而 Celeborn 能稳定完成所有测试案例
另外在数据验证中我们发现使用 Celeborn 会偶发存在丢数情况,对此我们反馈给社区开发人员一起联调测试,发现 Celeborn 确实存在有丢数的情况,问题详细记录在 CELEBORN-383。对此非常感谢社区的大力支持,帮助我们快速修复问题得以项目能准时上线。
三、与 Celeborn 共渡 800 天后的经验分享
在大数据计算领域,Shuffle 作为连接 Map 阶段和 Reduce 阶段的关键环节,其性能与稳定性直接影响着整个作业的执行效率。大数据平台运维团队目前运营着多个 Celeborn 集群,用上百个节点规模去支撑日均 PB 级 Shuffle 数据量、几十万应用,我们在过去 800 天的生产实践中,针对 Celeborn 这一新兴的 Remote Shuffle Service 进行了深度优化与调优。接下来的篇章中将系统性地分享我们在性能提升和稳定性保障两方面的实战经验,涵盖问题定位、优化思路、实现方案以及最终效果,为同行提供可落地的参考方案。
3.1 性能优化:从瓶颈突破到全面提升
在超大规模集群环境下,Celeborn 作为 Shuffle 数据的"交通枢纽",面临着诸多性能挑战。我们通过全链路监控和细粒度分析,识别出三个关键性能瓶颈点,并实施了针对性的优化措施。
3.1.1 异步处理 OpenStream 请求:解决读阻塞难题
问题现象与影响
在日常运维中,我们频繁观察到 Shuffle Read 耗时异常波动的情况:读取耗时从正常的几十毫秒突然增加到秒级甚至分钟级,同时读取数据量呈现断崖式下降。这种现象在业务高峰期尤为明显,直接导致作业执行时间延长 30%以上。
根因分析
通过分析 Celeborn Worker 的线程堆栈和 IO 等待情况,我们发现当 Worker 节点在进行大规模文件排序操作时,读取排序文件的 reduce 任务会同时发起对排序文件读取的 openstream 请求到 Worker,这些请求会长期占用线程直到排序结束,从而导致 Worker 的读线程数被占满,后续的读请求无法被处理形成恶性循环。
优化方案
我们通过修改客户端发起异步 openstream 请求方式去减少服务端线程被长时间占用的问题,从而降低对 fetch 请求的影响,相应的 pr 为:Github | apache | celeborn
3.1.2 小文件缓存:攻克高负载下的 IO 瓶颈
问题现象
在 Celeborn 集群负载超过 70%时,我们注意到一个反常现象:部分本应快速完成的 KB 级小文件读取操作,耗时却异常攀升至几十分钟级别。这类"小任务大延迟"问题导致简单作业的 SLA 难以保障。
根因定位
通过服务和机器负载的持续分析,我们发现高负载场景下小文件的读取的耗时主要用在 io 等待上,造成这一情况的主要原因是操作系统对于 io 的调度是遵循 FIFO 实现的,即按请求到达的顺序处理,在请求较多或较随机时,即使很小的文件也可能出现长时间等待的问题。
优化实现
在 Celeborn 中读写框架大概可以分为三个阶段:shuffle 文件写入阶段、shuffle 文件 commit 阶段、shuffle 文件读取阶段。shuffle 文件写入阶段主要是 spark 程序主动推送数据到 Celeborn 服务端,Celeborn 通过 pushHandler 将数据保留到服务端,在将数据写入磁盘对应的文件前会先将数据写入 FlushBuffer,当 buffer 被写满的时候才会生产 FlushTask 将数据做落盘处理,也以此来降低磁盘的 iops。而 shuffle 文件 commit 阶段则是对之前写入的文件做一个确认,服务端同时将在 FlushBuffer 中的数据做最后一次落盘处理。shuffle 文件读取阶段则通过服务端的 FetchHandler 处理 spark stage 的 shuffle read 请求,返回相应的 shuffle 数据。为解决上述的小文件读取瓶颈我们基于原有的读写框架设计了文件缓存体系来优化小文件访问,整体实现框架如下:
小文件缓存主要是通过增加一个 FileMemCacheManager 并作用在 shuffle 文件 commit 阶段实现,当服务端收到某个文件的 commit 请求时,会判断该文件是否之前有发生过刷盘操作,若没有且文件大小符合缓存策略,则会将文件缓存到 FileMemCacheManager 中去避免落盘。在 Shuffle 读取阶段,也会先校验文件是否被缓存,若缓存在内存中则从 FileMemCacheManager 中获取相应的文件数据,否则走原逻辑从磁盘中获取。
优化效果
通过灰度发布验证,优化后效果显著:
最差情况:Shuffle Read 最大耗时从 4 分钟降至 2 分钟以内
平均延迟:从 200ms+降至 60ms 以下
优化前压测服务指标
优化后压测服务指标
3.1.3 磁盘级线程控制:实现多盘负载均衡
问题现象
在多磁盘(12-24 块)配置的 Worker 节点上,我们经常观察到磁盘利用率不均衡现象:1-2 块磁盘的 IO 利用率持续保持在 100%,而其他磁盘却处于空闲状态。这种不均衡导致整体吞吐量无法随磁盘数量线性增长。
技术分析
Celeborn 原有的线程分配策略采用全局共享线程池,所有磁盘的读请求竞争同一组线程资源。当某块磁盘因数据倾斜或硬件故障导致 IO 延迟升高时,它会独占大部分线程,造成资源分配失衡。
具体表现为:
单盘异常可导致节点吞吐量下降 50%+
线程竞争引发大量上下文切换开销
无差别的重试机制加剧磁盘拥塞
优化方案
针对上述场景我们设计了磁盘级线程均衡策略去严格控制每个磁盘能使用的线程上限,以此来避免单盘异常导致所有读线程被占用的情况。
整体设计思路如下:
在设计方案上引入两个新的变量 FetchTask 和 DiskReader,FetchTask 主要用于把 fetch 请求的参数封装保留给到 DiskReader。而 DiskReader 则控制着单个磁盘读写并行度,每个磁盘对应一个 DiskReader,其不负责具体的 read 实现逻辑,read 逻辑还是在 ChunkStreamManager 中实现。
FetchTask 的数据解构如下:
DiskReader 控制磁盘读写并行度的逻辑大概如下:
尝试申请对当前磁盘的读操作
申请成功则占用处理锁并从 FetchTask 队列中获取待处理的 Task
处理 Task 中的 fetch 逻辑
释放处理锁
实施效果
优化后集群表现出更好的数据吞吐:
机器磁盘 io 利用率无明显差异
单盘异常对节点影响范围缩小 80%
优化后压测各磁盘表现情况
3.2 稳定性保障:从被动应对到主动防御
在保证性能优化的同时,集群的长期稳定运行同样至关重要。我们针对 Celeborn 在超大规模集群环境下暴露出的稳定性问题,构建了多层次保障体系。
3.2.1 动态负载感知的 Slot 分配策略
问题背景
Celeborn 提供 RoundRobin 和 LoadWare 两种 slot 分配策略,其中 RoundRobin 分配策略相对简单,其主要逻辑是获取当前可用磁盘并对这些磁盘做轮询分配。而 LoadWare 分配策略则需要先按照每个磁盘的读写压力进行排序分组,按照磁盘的压力等级逐级降低各个组的 slot 分配数量。在我们线上采用后者分配方式将 slot 分配到各个 Worker 尽量避免 worker 持续处于高负载的情况。在实际运营中我们发现当 worker 有磁盘出现 shuffle 压力时会很难恢复,有一部分原因可能是按照 LoadWare 分配策略集群仍可能往上面分配新的写任务从而恶化情况,虽然我们可以通过调整 celeborn.slots.assign.loadAware.num-
DiskGroups 和 celeborn.slots.assign.loadAware
.diskGroupGradient 参数来让部分磁盘不分配 slot,但这个参数相对比较难合理的评估出来,而且出现的节点往往只是个别的机器磁盘,通过原来分组的方式可能会影响其他同组正常的 worker 读写数据,为此我们决定保留原有的配置上实现了剔除高负载磁盘分配的策略,具体实现如下:
在上述流程中计算最大可容忍的高负载磁盘个数我们通过设置的 celeborn.slots.assign.loadAware
.discardDisk.maxWeight(默认配置 0.3)参数计算得来,其计算公式为集群磁盘总数 * celeborn.slots.assign.loadAware.discardDisk.maxWeight,例如我们总共有 500 块磁盘,按上述公式我们最多可能容忍 150 块磁盘不参与 slot 分配。对于高负载磁盘的判定,我们参考线上实际的平均读、写耗时阈情况将阈值设置为 200ms。通过引入上述策略,在凌晨高峰期时能及时剔除部分负载特别高的磁盘,防止 worker 持续恶化让服务性能更加稳定。
3.2.2 智能流量调度与权限管控
挑战分析
在管理 800+节点的 Celeborn 集群时,我们面临如下问题:
接入数量不可控:Master 地址暴漏后无法控制接入人群
任务流量不可控:异常大 shuffle 任务会冲击整个集群稳定性
故障隔离差:单集群问题影响全站业务
运维复杂度:多集群协同困难
客户端用户鉴权与任务切流
为了解决上述问题,我们在 Celeborn 客户端侧做了一些改造,用户接入 Celeborn 不再依赖 Mater URL 配置(spark.celeborn.master.endpoints),在客户端侧仅需要配置一个 Celeborn 集群标识,Celeborn 客户端会基于集群标识和用户账号向 VIVO 配置中心发起请求,通过配置中心获取真实的 Master URL
以上改造一个是解决了用户任务接入不受限制的情况,另一个是在客户端和集群中间多了一个配置层,一旦单个集群出现故障,可以通过在配置层修改 Master URL 进行热迁移。
服务端异常 shuffle 流量识别
Celeborn 开源版本提供一个 CongestionControl 功能,可以针对 user 粒度进行 push 过程的流量控制,在 CongestionControl 这套功能架构下有流量统计的模块代码(基于滑动窗口原理实现),可以基于该模块做 app 粒度的流量监控,识别 push 流量明显异常的 application
Celeborn 开源版 user 粒度 Push 异常流量识别流程图:
功能扩展:Shuffle Write 阶段 App Push 异常流量识别流程图
相较于社区版 user 粒度的异常流量识别,app 粒度的异常流量识别有更严格的判断,首先该 app 本身的流量要大于设定的阈值(我们当前设定的是 200MB/s),其次该 app 本身的流量要大于所有 app 平均流量/raito,raito 相当于一个权重比例,通过以上两种方式提升异常流量 app 的识别准确性。
服务端识别出异常 app 以后,会返回给客户端一个状态码,至于客户端如何处理,Celeborn 有提供不同的 PushStrategy 给用户选择(通过 celeborn.client.push.limit.strategy 配置),也可以自定义开发,常见的策略例如,客户端先暂停推送,间隔一段时间以后再恢复推动。
四、未来规划与展望
作为支撑日均 6PB 级 Shuffle 数据、13 万+应用的核心基础设施,我们的 Celeborn 集群已进入稳定运营期,刷盘耗时控制在 5ms 以内(平均 1.5ms),文件读取耗时低于 500ms(平均 50ms)。这一成绩的取得来之不易,但技术演进永无止境。后续我们会持续在运维平台化和社区跟进两大方向投入人力去持续优化现有集群,并进一步展望 Celeborn 在云原生、智能化等前沿领域的可能性。
4.1 运维平台化:从黑屏操作到统一管理
当前 Celeborn 集群的部署模式经历了从 Kubernetes 独立部署到物理机混合部署的演进,但运维操作仍以手工命令行为主,面临三大核心痛点:
操作风险高:扩缩容、配置变更等关键操作依赖人工执行,易出错且难以追溯
效率瓶颈:集群规模突破 800+节点后,人工运维响应速度跟不上业务需求
配置维护混乱:通过黑屏操作 Celeborn 服务很难统一集群配置
目前我们所有大数据组件都是通过 ambari 做统一管理,未来我们也计划将 Celeborn 服务加入 ambari 去管理,通过 ambari 去实现节点快速扩缩容、配置统一下发等替代人工黑屏操作的工作。
4.2 社区跟进:从版本滞后到行业对齐
当前集群仍运行 Celeborn 0.3.0 版本,落后社区最新版本多个重要迭代,错失了包括列式 Shuffle、向量化加速等关键特性,版本升级不仅是功能更新,更是技术债偿还的过程。Celeborn 作为下一代 Shuffle 基础设施,还有更广阔的创新空间值得我们探索,后续我们团队也会持续投入人力跟紧同行的步伐一起探索 Celeborn 的更多可能性。
版权声明: 本文为 InfoQ 作者【vivo互联网技术】的原创文章。
原文链接:【http://xie.infoq.cn/article/fffcb66988995c7a9eb8b7eae】。文章转载请联系作者。







评论