《Apache Flink 案例集(2022版)》——1.数据集成——伴鱼-伴鱼基于 Flink 构建数据集成平台的设计与实现(2) https://developer.aliyun.com/article/1228431
2. Merge任务
Merge 任务的前提是存量数据与增量数据都已经 ready,通过 _SUCCESS 文件进行标记。整个Merge 任务的工作流如下图所示:
校验文件标记是否存在,若不存在说明数据未 ready ,进行报警并退出工作流等待下次调度;
执行 Merge 操作,失败报警并退出工作流等待下次调度;
成功,退出工作流等待下次调度。
Merge 操作通过 Flink DataSet API 实现。核心逻辑如下:
加载存量、增量数据,统一数据格式(核心字段:主键 Key 作为同一条数据的聚合字段;CommitTs 标识 binlog 的提交时间,存量数据默认为 0 早于增量数据;OpType 标识数据操作类型,包括:Insert、Update、Delete,存量数据默认为 Insert 类型),将两份数据进行 union;
按照主键聚合;
保留聚合后 CommitTs 最大的数据条目,其余丢弃;
过滤 OpType 为 Delete 类型的数据条目;
输出聚合结果。
3. 容错性与数据一致性保证
大体可以从三个任务故障场景下的处理方式来验证方案的容错性: 存量任务异常失败:通常是备份恢复失败导致,DS 任务将发送失败报警,因数据库平台暂不支持恢复重试,需人工介入处理。同时Merge 任务检测不到存量的 _SUCCESS 标记,工作流不会向后推进。
增量任务异常失败:Flink 自身的容错机制以及实时计算平台的外部检测机制保障增量任务的容错性。若在Merge 任务调度执行期间增量任务尚未恢复,将误以为该小时无增量数据跳过执行,此时相当于快照更新延迟(Merge 是将全天的增量数据与存量聚合,在之后的调度时间点如果增量任务恢复又可以聚合得到最新的快照),或者在增量任务恢复后可人为触发Merge 任务补数。
Merge 任务异常失败:任务具有幂等性,通过设置 DS 任务失败后的重试机制保障容错性,同时发送失败报警。
数据的一致性体现在 Merge 操作。两份数据聚合,从代码层面一定可以确保算法的正确性 (这是可验证的、可测试的),那么唯一可能导致数据不一致的情况出现在两份输入的数据上,即存量和增量,存在两种情况:
存量和增量数据有交叠:体现在初始存量与整点的增量数据聚合场景,由于算法天然的去重性可以保证数据的一致。
存量和增量数据有缺失:体现在增量数据的缺失上,而增量数据是由 Flink 将 Kafka 数据写入 Hive 的,这个过程中是有一定的可能性造成数据的不一致,即分区提交后的乱序数据。虽然说乱序数据到来后的下一次 checkpoint 时间点分区将再次提交,但下游任务一般是检测到首次分区提交就会触发执行,造成下游任务的数据不一致。
针对 Flink 流式写 Hive 过程中的乱序数据处理可以采取两种手段:
一是 Kafka 设置单分区,多分区是产生导致乱序的根因,通过避免多分区消除数据乱序。
二是报警补偿,乱序一旦产生流式任务是无法完全避免的 (可通过 watermark 设置乱序容忍时间,但终有一个界限),那么只能通过报警做事后补偿。
问题转换成了如何感知到乱序,既然乱序数据会触发前一个分区的二次提交,那么只需要在提交分区的时候检测前一个分区是否存在 _SUCCESS 标记便可以知晓是否是乱序数据以及触发报警。
未来规划
伴鱼正在推进实时数仓集成任务的接入,以提供更统一的体验。