找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1927

积分

0

好友

257

主题
发表于 13 小时前 | 查看: 2| 回复: 0

导读

本文分享蚂蚁集团基于开源高性能计算库 Velox 构建流批一体向量化引擎 Flex 的技术实践,涵盖了其架构设计、核心功能开发、以及如何在保障正确性与提升易用性方面所做的探索,并展望了未来的工作方向。

01 向量化技术现状

1. 核心趋势:向量化技术发展现状

向量化技术的核心原理是利用 SIMD(单指令多数据流)指令集。简单来说,就是一条指令可以同时处理多条数据,相比于传统的单条指令处理单条数据,它能带来更高的计算并行度。

下图展示了不同计算模式的并行度对比。可以看到,无论是单线程还是多线程场景,使用向量化技术后,性能都能获得指数级的提升。
行业向量化技术现状分析图

向量化技术发展现状

  • 硬件支持:现代CPU提供了更多、更大的寄存器资源。
  • SIMD指令集:CPU原生支持,如x86平台的SSE、AVX指令集,ARM平台的Neon指令集等。
  • 编译器优化:GCC、LLVM等主流编译器已实现自动向量化功能,能自动识别并优化可向量化的代码。
  • 专用库:如 xsimd 等跨平台的SIMD抽象库,方便开发者编写高性能可移植代码。

对于计算密集型应用,向量化技术能显著提升效率。如今,绝大多数处理器都支持SIMD,编译器层面的支持也日趋成熟,为向量化在大数据领域的应用铺平了道路。

2. 为何选择 Photon 引擎?

在大数据领域,向量化已经成为重要的性能优化方向。Databricks 的 Photon 引擎就是典型代表,它是一款完全基于 C++ 开发的闭源向量化引擎。根据公开信息,Photon 在 TPC-DS 1TB 基准测试中带来了额外2倍的性能提升,在实际业务负载中,客户观察到的平均性能提升可达3至8倍。
行业向量化技术现状与选型对比图

Photon的成功激发了业界的广泛关注,各大主流分布式计算引擎也纷纷向向量化方向发力。例如,英特尔开源的 Gluten 项目探索了 Spark + Velox 的方案;Comet/Blaze 项目尝试了 Spark + DataFusion(一个基于Rust的向量化库);还有基于 Presto + Velox 的实验方案。

然而,作为流批一体计算引擎的代表,Apache Flink 在原生向量化能力方面一直存在空白。这促使我们开始思考,能否为 Flink 也注入向量化的能力?

02 系统架构

1. Flex 框架:架构选型与设计理念

在项目启动时,我们的目标很明确:不重复造轮子。业界已有像 Velox 这样经过验证的高性能开源向量化库,因此我们决定借鉴 Gluten 的思路,基于 Velox 为 Flink 构建向量化能力,并与 Gluten 社区保持了紧密的合作交流。

但挑战也随之而来。Velox 是面向批处理设计的,其计算模型无法处理流式计算中常见的“回撤”操作,两者语义存在冲突。同时,直接套用 Gluten 的 Substrait 执行计划模型不仅工作量大,还无法支持 Flink 核心的“有状态算子”。

2. 引擎选型最终方案

经过验证,我们正式立项了 Flex 项目,其核心公式为:
Flex = Flink + Velox

“Flex”取自“flexible”,寓意其设计目标为灵活、可插拔。

选型依据

  • 可扩展性:提供一套高可扩展的向量化算子与函数库。
  • 性能表现:采用经行业验证的高性能 C++ 库(Velox)。
  • 社区与生态:依托 Velox 和 Flink 活跃的社区与持续壮大的生态系统。

3. 集成策略

我们对比了多种集成策略,主要考虑两个问题:

  • 是否采用 Gluten 的 Substrait 执行计划模型?
  • 如何实现对有状态算子的支持?

下图展示了我们的方案对比。Plan Option1 类似 Gluten 方案,需要插入行转列/列转行的算子,且不支持状态算子,工作量巨大。
Flex架构设计选择与集成策略对比图

最终,我们选择了 Plan Option2。该方案将批处理、行列转换以及 Velox 的列式计算逻辑都封装到一个统一的算子内部,从而能够同时支持状态算子和非状态算子,大大简化了集成复杂度。

Flex的整体架构分层清晰,主要包括以下模块:
Flex统一向量化引擎架构图

  • JNI 适配层:负责 Java (Flink) 与 C++ (Velox) 之间的通信。
  • 原生算子层:负责将 Flink 的执行计划转换为可由 Velox 执行的原生计划。
  • 执行计划转换层:将 Flink 面向行的 RowData 转换为面向列的 ColumnRowData 数据结构。
  • 数据转换层:处理行列数据格式之间的高效转换。
  • 回退层:在算子或函数不支持原生执行时,自动回退到 Flink 原生的 Java 实现。
  • 统一内存管理层:对 Native 侧的内存进行统一管理和生命周期控制。

03 Flex:核心功能开发与实现

我们围绕 Flex 在功能性、性能、正确性、易用性和稳定性方面开展了大量工作。

1. 性能优化与核心架构

Flex核心功能开发概览图

  • 执行计划层优化:提供丰富的优化规则集。例如,将包含 SIMD 函数表达式的 Calc 算子翻译成 NativeCalc,以提升表达式计算性能。
  • 原生算子:支持 SLS、ODPS、Paimon 等原生连接器,使数据能以列式格式(如 Arrow)直接流转,避免额外的行列转换开销。
  • 高效数据表示:采用基于 Arrow 的 ColumnRowData 数据结构,实现高性能的列式处理流水线。
  • 丰富的 SIMD 函数库:对大量 Flink 内置函数使用 SIMD 指令集进行了重写,目前支持超过 15 个字符串函数以及大量数学函数。

2. Projection Reorder 投影重排

在实际应用中,我们发现一些SQL查询引用了大量字段,但实际参与计算的字段很少,数据转换开销成为瓶颈。
Flex核心功能开发:Projection Reorder示意图

我们没有采用社区中让 UDF 也以 Native 方式运行的复杂方案,而是巧妙地将 Calc 算子拆分为两个。这样,含有 SIMD 函数的表达式部分被剥离出来,由 NativeCalc 高效执行,而包含 UDF 的部分则按原逻辑处理,完美绕过了性能瓶颈。

3. 针对关联算子条件的 SIMD 加速

我们同样对 Correlate(关联)算子进行了加速。在流计算中,Correlate 通常用于实现流表 JOIN,其条件判断部分若包含 SIMD 函数,则可以拆分出来进行加速。
Flex核心功能开发:SIMD加速关联算子条件图

4. 针对流-流连接条件的 SIMD 加速优化

这个思路可以扩展到双流 JOIN。如果 JOIN 的 ONWHERE 条件中包含 SIMD 函数,同样可以将其拆分为独立的 NativeCalc 进行加速。
Flex核心功能开发:SIMD加速流-流连接条件图

5. 支持原生 Paimon 源/汇/DIM 及规则资源注入

Paimon 数据湖是我们实现性能突破的关键场景。Paimon 内部使用 Parquet 存储格式,并提供了 Arrow 格式的数据接口。我们打通了 Flink RowData 到 Paimon Arrow 结构的直接转换链路,避免了中间格式转换,显著提升了性能。
Flex核心功能开发:原生Paimon支持与资源注入架构图

大规模上线会遇到各种稳定性问题。为了确保用户作业的稳定,我们基于规则为使用了 Native 算子的作业自动注入额外的资源。

执行计划可视化:为了方便用户和开发者直观地识别哪些算子在以 Native 模式运行,我们在算子名称前统一加上了“Native”前缀。
Flex核心功能开发:执行计划可视化示例图

6. 细粒度可配置回退机制

Flex核心功能开发:细粒度回退机制说明图

由于 Velox 和 Flink 在某些函数的具体行为上可能存在语义差异,我们设计了一套精细的回退控制机制:

  • 黑名单机制:支持基于函数签名的细粒度黑名单,精准控制哪些函数或类型不进行向量化。
  • 智能卸载:仅当表达式完全由已支持的 SIMD 函数构成时,才将其转换为 NativeCalc。
  • 自动回退:对 TIMESTAMP、DECIMAL 等复杂 SQL 类型,提供自动回退保障。

7. 可配置函数映射

  • 支持 SQL 函数的自定义映射。例如,将 Flink 的某个函数名映射到 Velox 中语义相同的另一个函数,避免重复开发。
  • 在 Flex 中提供原生实现,并配备优先级覆盖机制,使得问题修复和迭代更快捷(编译时间从数小时缩短到几分钟)。

04 Flex:正确性与数据完整性保障

正确性是金融级应用的底线。Flink(Java)和 Velox(C++)是两套独立的引擎,如何保证数以百计的函数语义完全一致?我们不能仅靠假设,必须建立自动化的验证体系。为此,我们开发了函数级和作业级两套验证系统。

1. 自动化函数级验证

Flex正确性保障:自动化函数级验证框架图

  • 无缝复用:直接复用 Flink 自身丰富的单元测试用例。
  • 双栈执行:同时在 Flink 的旧栈(Legacy)、新栈(New)以及 Flex(Velox)上执行测试。
  • 逐比特比对:自动比对三者的输出结果,任何细微差异都会被捕获。

关键发现与影响

  • 发现了 Flink 原生 Java 函数中存在的 4 处 正确性问题。
  • 发现了大量 Flink 与 Velox 在函数行为上的语义不一致问题。
    这套工具不仅帮助我们校准了 Velox 的实现,甚至反过来帮助完善了 Flink 引擎自身。

2. 端到端自动化对比框架 Minos

函数级正确不代表组合起来就正确。因此,我们开发了作业级的自动化比对框架 Minos
Flex正确性保障:端到端自动化对比框架Minos图

它能将用户的一个 SQL 作业,自动改写成两个并行作业(一个走原生Java路径,一个走Flex向量化路径),并将两者的计算结果写入存储。系统会定时对两个结果进行全量比对,生成详细的核对报告,确保万无一失后才敢大规模应用。

05 Flex 框架:提升易用性与开发者体验

为了让用户和开发者能顺畅地使用 Flex,我们做了大量“看不见”的工作。

1. 自动化兼容性分析器

Flex易用性提升:开发者工具集图

  • 静态分析作业的执行计划,在用户迁移前就能判断其作业是否能以原生模式运行,大幅缩短接入周期。
  • 通过扫描线上真实作业,提前发现大量暂不支持的函数,为后续开发提供明确优先级。

2. 基于 JMH 的端到端性能验证框架

  • 用于量化验证向量化带来的实际性能收益,并精准定位任何可能出现的性能回退。
    Flex易用性提升:JMH性能测试数据图
    从上图的性能测试数据可以看到,像 positionlocateinstr 这类字符串查找函数,在使用 SIMD 优化后,性能提升了十倍以上

3. 向量化监控面板

为所有向量化作业提供实时洞察与核心指标监控,让运行状态一目了然。

06 应用情况与运行成效

目前,Flex 已经在蚂蚁集团内部实现了大规模落地,并取得了显著的成效。
Flex应用成效与业务价值总结图

  • 规模:已支持 6800+ 个线上作业。
  • 集成:已在内部 Flink 1.18.1.2 版本中默认启用
  • 资源:累计节省超过 3万+ 个 CPU 核心。
  • 性能:Paimon 表端到端 TPS 提升 50%;在曝光、点击、访问等蚂蚁最高流量的数据管道中,TPS 提升达到 59%
  • 场景:已广泛应用于广告投放、碰一碰、闪购、灵光平台、资金调度、大规模安全防护等核心业务场景。

07 未来工作方向与重点

Flex未来工作方向规划图

  1. 支持全链路向量化:突破当前仅支持部分算子的限制,让数据在更多算子间以列式格式高效流转,避免不必要的行列转换开销。
  2. 高效低开销的数据转换:优化当前的 Arrow 中转链路,探索从 Flink RowData 直接转换为 Velox RowVector 的更高效方式。
  3. 支持更多状态算子:探索对窗口聚合等有状态算子进行向量化加速的可能性。
  4. 支持更多架构:扩展对 ARM、GPU 等异构计算架构的支持。
  5. 支持完整 SQL 类型:完善对复杂 Row、Array、Map 等数据类型的原生支持。
  6. 扩展 SIMD 函数库:持续增加更多的数学函数和其他类型的 SIMD 函数实现。

如果你对数据库/中间件的底层性能优化技术感兴趣,欢迎来云栈社区交流探讨。




上一篇:OpenClaw与OPC框架:解析多层AI代理架构如何驱动一人公司软件自动化
下一篇:AI时代,有想法的程序员如何实现万倍碾压?
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-3 21:59 , Processed in 0.441427 second(s), 42 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表