一、端到端的一致性概念

端到端的一致性保证,意味着结果的正确性贯穿了整个流处理应用的始终;每一个组件都保证了它自己的一致性,整个端到端的一致性级别取决于所有组件中一致性最弱的组件。

  • source端

需要外部源可重设数据的读取位置.

例如使用的Kafka Source具有这种特性: 读取数据的时候可以指定offset

  • flink内部

依赖checkpoint机制

  • sink端

需要保证从故障恢复时,数据不会重复写入外部系统. 有2种实现形式:

  1. 幂等(Idempotent)写入

所谓幂等操作,是说一个操作,可以重复执行很多次,但只导致一次结果更改,也就是说,后面再重复执行就不起作用了。

  1. 事务性(Transactional)写入

需要构建事务来写入外部系统,构建的事务对应着 checkpoint,等到 checkpoint 真正完成的时候,才把所有对应的结果写入 sink 系统中。对于事务性写入,具体又有两种实现方式:预写日志(WAL)和两阶段提交(2PC)

二、checkpoint 原理

        1.Flink 使用了 checkPoint 来 保证 exactly-once。Flink集群在某个算子因为某些原因(如 异常退出)出现故障时,能够将整个应用流图的状态恢复到故障之前的某一状态,保证应用流图状态的一致性.

  2.Flink是 如何来做这个 checkPoint 的呢?

解释: Flink的checkpoint机制原理来自"Chandy-Lamport algorithm"算法(分布式快照算法)的一种变体: 异步 barrier 快照(asynchronous barrier snapshotting)

这种checkPoint 机制可以再不影响其他算子的情况下,对每一个算子在处理某一时刻 数据的状态进行 checkpoint

步骤:

1>再做checkPoint之前,(jobManager的组件)Checkpoint Coordinator 向所有 source 节点 trigger Checkpoint. source端会 将多个barrier插入到数据流中,然后作为数据流的一部分随着数据流动(有点类似于Watermark).这些barrier不会跨越流中的数据.

2>barrier会把数据流分成两部分: 一部分数据进入当前的快照 , 另一部分数据进入下一个快照, 每个barrier携带着快照的id. barrier 不会暂停数据的流动, 所以非常轻量级.  在流中, 同一时间可以有来源于多个不同快照的多个barrier, 这个意味着可以并发的出现不同的快照(多个算子并发做快照).

source 节点向下游广播 barrier, 下游的task 只有收到所有的input 的barrier 才会执行 Checkpoint

存入 checkpoint,将备份数据的地址通知给 Checkpoint coordinator。这里涉及到 barrier对齐和不对齐。

3>sink 节点收集齐上游两个 input 的 barrier 之后,会执行本地快照,

4>sink 节点在完成自己的 Checkpoint 之后,会将 state handle 返回通知 Coordinator。

5>Checkpoint coordinator 收集齐所有 task 的 state handle,就认为这一次的 Checkpoint 全局完成了,向持久化存储中再备份一个 Checkpoint meta 文件。

三 barrier对齐 和 不对齐

 如果要实现严格一次, 则要执行barrier对齐

flink 写入kudu flink 写入和消费Kafka不同认证_hadoop

拥有两个输入流的 Operators(例如 CoProcessFunction)会执行 barrier 对齐(barrier alignment) 以便当前快照能够包含消费两个输入流 barrier 之前(但不超过)的所有 events 而产生的状态。

对齐:

假设只有两条流(字母流,数字流)

        1.  当operator 收到 数字流的 barrier (第n个)时, 他就不能 计算 (能接收) 来自该流的任何数据记录,直到 它从 字母流 收到 同一个 barrier(第n个) 为止。接受到的数据都是 快照 n的 记录。否则,他会包含 快照 n+1 的数据。

     2.收到barrier  n (数字流的数据 被暂时搁置,这些数据存入缓冲区中,不被处理)

上图红色的 竖线 就代表 barrier

        3.当接收到 所有的 barriern 时,Operator 就会把 缓冲区中的 pending 的输出数据 发出去,然后会把 checkPoint barrier n 接着往下游发送 。并对自身进行快照。

不对其:

依照上述(对齐)第二点 所说的,

假设不对齐, 在字母流的Checkpoint barrier n到达前, 已经处理了1 2 3. 等字母流Checkpoint barrier n到达之后, 会做Checkpoint n.  假设这个时候程序异常错误了, 则重新启动的时候会Checkpoint n之后的数据重新计算. 1 2 3 会被再次被计算, 所以123出现了重复计算.

四、两阶段提交

 kafka producer作为sink,采用两阶段提交 sink,需要实现一个 TwoPhaseCommitSinkFunction

 

flink 写入kudu flink 写入和消费Kafka不同认证_hadoop_02

1.jobmanager 触发 checkpoint 操作,barrier 从 source 开始向下传递,遇到 barrier 的算子将状态存入状态后端,并通知 jobmanager

2.第一条数据来了之后,开启一个 kafka 的事务(transaction),正常写入 kafka 分区日志但标记为未提交,这就是“预提交”

3.sink 连接器收到 barrier,保存当前状态,存入 checkpoint,通知 jobmanager,并开启下一阶段的事务,用于提交下个检查点的数据

4.jobmanager 收到所有任务的通知,发出确认信息,表示 checkpoint 完成

5.sink 任务收到 jobmanager 的确认信息,正式提交这段时间的数据

6.外部kafka关闭事务,提交的数据可以正常消费了