Page 274 - 《软件学报》2025年第7期
P. 274
秦政 等: 面向 Apache Flink 流式分析应用的高吞吐优化技术 3195
合. 本文提出的键级水位线如图 9 所示, 键级水位线与主键相关联. 每个算子子任务上具有对应水位线信息, 每个
主键相关的水位线随着数据在算子间传递. 对于不同数据产生源间数据乱序, 键级水位线相比子任务级水位线而
言: 一方面, 使用子任务级水位线可能需要长时间等待所有事件的到达, 从而导致大量中间状态的保持, 键级水位
线可以减少这种不必要的状态保持, 因为每个键的窗口可以独立于其他键关闭和清理; 另一方面, 由于每个键的水
位线独立更新, 窗口操作可以更快地完成, 从而对于有实时性要求的应用, 可以实现更低的处理延迟. 键级水位线
提供了一种更精细的控制方法, 可以减少数据的乱序问题. 即使不同数据源通信效率差异造成生成时间与到达时
间的紊乱, 系统也会基于计算任务需求和相应的键级水位线进行合理等待, 不会带来额外的乱序处理操作. 图 8
中, 当采用键级水位线设计接入 t = 3 数据 (k 1 , v, 3) 时, 只需要对该主键所涉及的 1 条数据进行重算, 减小了计算
和等待开销. 键级的水位线在该场景下, 可以减少迟到数据比例, 从而减少基于迟到数据的更新操作, 提高系统吞
吐率.
Kafka 数据交换
键级水位线 水位线流动
DataSource 赋予 (k 1 ,w 1 ) KeyBy (k 6 ,w 6 )
键级水位线
DataSource (k 4 ,w 4 ) KeyBy (k 3 ,w 3 )
赋予
键级水位线
DataSource (k 7 ,w 7 ) KeyBy (k 7 ,w 7 )
赋予
图 9 主键级水位线示意图
本文设计了有状态处理函数上的键级水位线机制, 其核心是水位线的更新和定时事件的触发. 在 Flink 中, 用
户需要在 Process 中实现基于子任务级水位线的迟到元素检测和处理、非迟到元素处理. 本文提出的键级水位线
设计基于设计模式中的模板模式, 抽象分离出有状态处理函数中的基于主键级水位线的迟到元素检测、迟到元素
处理、非迟到元素处理 3 部分逻辑. 同时, 也支持子任务级水位线上的迟到元素检测和处理, 从而兼容原有的水位
线语义, 并可以根据子任务级水位线下的迟到元素数量与主键级水位线下的迟到元素数量, 评估优化当前水位线
性能. 为了检测并触发定时事件, 本文基于红黑树存储定时事件, 以实现对数时间复杂度的定时事件注册和常数时
间复杂度的最早定时事件查询.
键级水位线机制适用于不同数据源间存在数据乱序、同一数据源内部数据相对有序、各主键间计算任务相
对独立的场景. 该机制能够在保证结果正确性的前提下, 避免不必要的乱序数据等待与重处理.
由于键级水位线会带来额外的空间和计算开销, 该机制实际提供了一种最细粒度的控制方式, 用户可以在键
级和子任务级间自主调控. 键级水位线机制同样支持 N-键级水位线, 即 N 个 Key 共享同一水位线, 从而达到空间
开销与系统性能间的均衡.
4.2 动态负载分发策略
KeyBy 算子在流处理中具有其特殊性, 其根据键相关信息对流数据进行分区, 对于分布式流处理框架来说, 对
其做优化适用于大部分的流处理应用. 另一方面, KeyBy 算子涉及状态的分区存储和管理, 比如计算滑动窗口的平
均值或者跟踪某个项的运行总数. 因而, 相较于传统的数据倾斜和负载均衡问题, KeyBy 算子的负载分发涉及更多
流式处理特性, 包括实时窗口内数据分布信息和历史状态信息. 本节首先针对常见的数据分布场景和集群配置情
况提出了 4 种负载分发优化策略; 接着, 设计了在线监测机制与负载均衡策略动态配置机制, 将负载分发策略融入
流式处理系统中, 并提供可用的切换机制; 最后, 基于 ABS 算法 [45] 实现了无中断键值状态交换机制, 保证在动态负
载均衡切换时不中断流式分析应用, 保障系统的可用性.
4.2.1 负载分发策略
f : K → N, f 将数据主键 映射到 Flink 算子的子任
本文将负载均衡抽象为数据分配映射的目标优化, 即 k ∈ K
务 n ∈ N 上, 使得 maxC (n)/minC (n) 最小化, 其中 C : K → Z 是子任务节点处理的数据量, 从而提高负载均衡度, 增

