快手 AB 指标生产场景从 Spark 切换到 Doris:提速 145 倍、资源降 72%,刷新集群规模记录

快手 AB 指标生产场景从 Spark 切换到 Doris:提速 145 倍、资源降 72%,刷新集群规模记录
AB 指标计算链路的性能与成本压力快手 AB 实验平台是公司级指标计算底座服务全公司业务线支撑公司级业务决策。在 Spark 时代AB 指标计算面临计算慢和成本高的问题。以核心指标模板为例单链路计算耗时约 21 分钟业务决策被迫延后在 100% 流量推全场景下计算成本随实验数量增长线性上升。基于此团队将生产链路从 Spark 迁移到 Doris。目前快手 Doris AB 集群规模包括 5 个 FE 节点、2000 个 BE 节点、10 万 CU、数百 TB 内存池并划分为 12 个逻辑计算组。近 14 天审计中集群承载数百万个任务日均任务量达几十万级扫描数据量达 40TB、千亿级行。在这一规模下需从多个层面系统优化。为什么 Doris 比 Spark 更适合该场景Doris 相比 Spark 的优势源于三方面执行模型差异。一是 Pipeline 执行引擎减少线程等待Spark 在 Shuffle 时数据需落盘下游线程阻塞而 Doris 可让出线程执行其他任务减少 CPU 空转二是向量化执行提升批处理效率Spark SQL 用行式 Internal RowDoris 是全链路列式 Block更适合 CPU SIMD 批量处理三是 C 运行时降低 JVM 相关开销Spark 运行在 JVM 上有 GC 和 JIT 开销Doris 用 C 编译后的机器码执行启动后执行效率高。对于快手 AB 指标计算更大收益来自业务计算模型与 Doris 执行机制的匹配。因 AB 指标计算模板长期稳定团队围绕执行链路深入优化最终实现 145 倍性能提升。关键优化从减少数据流动到压缩计算热路径完成引擎迁移后团队围绕 AB 指标计算模板特点对数据分布、执行计划等进行针对性系统优化。AB 指标计算链路输入固定为累计分流表和指标宽表输出按实验、分组、桶等维度聚合结果集一般为百行到万行。完整计算过程主要包括四步其中第二步和第三步是优化主战场。该场景特点是 Join Key 长期固定为 UID聚合维度相对稳定具备持续专项优化条件。存储优化用 Colocate Join 消除跨节点 Shuffle核心优化是 Colocate Join其思路是在数据写入阶段按 UID 对数据哈希分桶使相同 UID 数据落在同一机器、同一分桶内。这样查询时分流表和行为表可在本地完成 Join无需跨节点 Shuffle 或搬运大量数据大部分数据在本地节点内消化网络只传输少量结果集。落地 Colocate Join 需保证建表按 UID 哈希分桶参与 Join 的两张表分桶数严格一致。表结构调整后需通过 EXPLAIN 检查执行计划只有出现 Colocated 才说明优化生效。计算优化降低去重聚合与 UDF 热路径开销Local Distinct Grouping Sets减少全局 ShuffleColocate 优化消除了 Join 的跨节点 Shuffle但去重算子仍可能引入全局 Shuffle 开销。在 AB 指标计算中SQL 广泛使用 _Grouping Sets_ Doris 原生执行框架无法覆盖 _Grouping Sets Distinct_ 组合场景会触发全局 Shuffle。团队设计并实现了 Local Distinct Grouping Sets 改写机制将去重计算前移至各计算节点本地执行先完成局部 Distinct再进行全局聚合汇总降低 Shuffle 成本。该优化有透明改写和显式调用两种模式。不过这项优化并非在所有场景都优于原执行计划对于原生 COUNT DISTINCT 场景改写为 Local 模式会引入约 6 秒的 Barrier 等待开销。因此更适合 Shuffle 成为主要瓶颈的场景是否启用需结合 Profile 和实际执行计划判断。UDF Native 化压缩 CPU 热路径成本AB 实验链路中分流判定 UDF 是核心计算逻辑之一虽单次调用计算开销小但因数据规模大成为典型的 CPU 热路径。通过 Profile 分析Java UDF 占约 80% CPU 开销主要瓶颈来自 JVM 调用与对象创建开销。团队将其改写为 C Native UDF消除 JNI 调用成本并深入 STL 层优化包括字符串拼接、实验配置访问和用户对象构造等方面。最终三项优化叠加使 AB 实验模板整体执行性能提升约 3 倍。调度优化用隔离、反压和优先级保障 SLA当 Doris 承载规模扩展到数十万级日任务后需引入调度层进行系统级治理。第一层是物理隔离将 AB 集群拆分为 12 个独立计算组不同优先级业务在不同计算组运行资源配额独立控制避免跨业务干扰。第二层是组内控制在单个计算组内叠加并发上限控制、上游反压机制和优先级队列调度保障单组稳定性。物理隔离和组内控制共同保证高优链路在高峰期满足 SLA。稳定性治理元数据治理被动修复到主动治理Doris FE 作为元数据管理节点元数据信息保存在 JVM 内存中。生产运行中暴露出单表维度和集群维度两类风险单表分区规模增长至万级时FE 生成 Checkpoint 会触发上限约束导致进程异常退出Tablet 达到千万级后FE 元数据对象在堆内累积Master FE 内存峰值接近 400GB 上限频繁触发 Full GC。团队引入元数据容量建模与监控体系通过统计分析得到单个 Tablet 在 FE 内存中平均占用约 11KB 的经验结论可提前预测 FE 内存压力。FE 优化压缩元数据结构缩短恢复窗口团队对元数据结构进行压缩优化引入 Cloud Table Inverted Index裁剪 Cloud 场景无用字段替换部分集合结构降低对象开销。在百万级 Tablet 压测中该优化使元数据内存占用从 4.16GB 降至 1.49GB整体下降约 64%在千万级规模下Checkpoint 峰值阶段可节省数十 GB 内存。针对 FE 运行在超大堆场景团队对 G1 GC 参数进行针对性调整。调优后Master FE 的内存峰值由 370 GB 降至 270 GB24 小时线上验证期间未发生 Full GC。最后团队对 FE 启动恢复流程进行并行优化使整体 FE 恢复窗口缩短至约 10 分钟。这些实践表明元数据治理应提前纳入系统架构设计。收益总结从引擎迁移到计算体系重构快手 AB 指标生产场景从 Spark 升级到 Doris 性能最大提升 145 倍、资源消耗下降 72%得益于 Doris 的架构优势和快手基于 Doris 针对 AB 场景的深度优化。快手 AB 指标生产场景的大规模落地证明 Doris 适合该场景为社区提供了基于 Doris 构建 AB Test 平台的最佳实践还刷新了全球最大单个 Doris 集群规模记录。关于 AB 指标生产和更多应用场景、Doris 落地和优化等主题欢迎加入 [Doris 社区](https://doris.apache.org/)交流。