概述

两阶段提交(two-phase commit)缩写为2PC。
分为两步:Pre-Commit(预提交)阶段、Commit阶段。
保证Flink与外部系统exacllty-once关键原理。
需要外部系统有必要事务支持。
Kafka-0.11.0.0及以上对事务支持。
两次Checkpoint间的所有写入作为一个事务提交给Kafka。

Pre-Commit阶段(预提交)

barrier经过operator时,state写入StateBackend。传递到Sink时,Sink会向外部系统提交pre-commit状态,即告知外部系统pre-commit阶段完成。
此阶段封装KafkaProducer.flush()方法刷写消息数据,但还未真正提交。

Commit阶段

image.png

  1. Flink Master(JobManager)收到所有算子Checkpoint成功后。
  2. 调用TwoPhaseCommitSinkFunction.notifyCheckpointComplete()通知所有operator Checkpoint完成。
  3. Sink向外部系统提交commit状态,即告知外部系统commit阶段完成。其他算子收到通知不做任何动作。

此阶段封装了KafkaProducer.commitTransaction()。

备注

如果pre-commit完成后发生崩溃,恢复后可以继续进行commit阶段也可以回滚整个事务。如果所有Checkpoint完成该进行二次提交了但是集群挂了在此启动直接二次提交可以更完美。所以当应用从checkpoint恢复之后TwoPhaseCommitSinkFunction总是会发起一个抢占式的commit。这种commit必须是幂等性的。

参考

干货:Flink+Kafka 0.11端到端精确一次处理语义实现
https://cloud.tencent.com/developer/news/291243

https://flink.apache.org/features/2018/03/01/end-to-end-exactly-once-apache-flink.html