Flink-Kafka 连接器及exactly-once 语义保证

Flink的容错机制

当 Flink 开启了 checkpoint 的时候,Flink 会一边消费 topic 的数据,一边定时的将 offset 和 其他 operator 的状态记录到 checkpoint 中。

如果遇到了 job 失败的情况,那么 Flink 将会重启 job,从最后一个 checkpoint 中来恢复 job 的所有状态,然后从 checkpoint 中记录的 offset 开始重新对 topic 进行消费。

Flink 如何保证端到端的 exacly-once 语义

Flink 基于异步轻量级的分布式快照技术提供 Checkpoint 容错机制。

Flink 分布式快照的核心概念之一就是数据栅栏(barrier)。

Barrier 在数据源端插入,和数据流一起向下流动,(Barrier不会干扰正常的数据,数据流严格有序)

当 snapshot n 的 barrier 插入后,系统会记录当前 snapshot 位置值 n (用 Sn 表示),在 apache kafka 中,这个变量表示某个分区最后一次消费的偏移量。

这个位置值 Sn 会被发送到一个称为 checkpoint coordinate 模块(即 Flink 的 JobManager)。

barrier 插入后,随着数据一起向下游流动,从一个 operator 到 另一个 operator。

当一个 operator 从其输入流接收到所有标识 snapshot n 的barrier 时,它会向其所有输出流继续插入一个 标识 snapshot n 的 barrier。

当 sink operator (DAG 流的终点)从其输入流接收到所有 barrier n 时,它向 checkpoint coordinate 确认 snapshot n 完成。当所有 sink 都确认了这个快照,快照就被标识为完成。

有一个特性是,某个operator 只要一接收到 某个输入流的 barrier n,它就不能继续处理此数据流后续的数据,后续的数据会被放入到接收缓存(input buffer)中(如上图红框标识的缓存区)。

只有当 operator 从最后一个流中提取到 barrier n 时,operator 才会继续发射出所有等待向后发送的数据,然后发送 snapshot n 所属的 barrier。

那么如何保证 exactly-once 语义的?

假设现在 barrier 现在在 source 和 map 之间,任务挂掉了。下一次 Flink 会自动的重启任务,从上一次的快照中恢复。

会从 kafka 的上一次消费的地方开始消费。由于上一次 sink 还未接收到 所有的 barrier 就挂掉了,上一次的数据都被缓存在 input buffer 中,还未到 sink 中处理,这一次重新消费的记录会被sink继续处理。也就是没有多消费一条记录,也没有少消费一条记录。

原文地址:https://www.cnblogs.com/zourui4271/p/13544874.html