深入理解Flink --- End-to-End(端到端) Exactly-Once语义(两阶段提交)

Flink内部的Exactly-Once语义是基于Asynchronous Barrier Snapshotting(ABS)实现的.

那么Flink和外部系统(如Kafka)之间的消息传递如何做到exactly once呢?

问题所在:

flink
如上图,当sink A已经往Kafka写入了数据,而sink B fail。
根据Flink的exactly once保证,系统会回滚到最近的checkpoint,但是sink A已经把数据写入到kafka了。
Flink无法回滚kafka的state,因此,kafka将在之后再次接收到一份同样的来自sink A的数据,这样的message delivery便成为了at least once。

解决方案: Two phase commit

Flink采用Two phase commit来解决这个问题。

Phase 1: Pre-commit
Flink的JobManager向source注入checkpoint barrier以开启这次snapshot,
barrier从source流向sink,
每个进行snapshot的算子成功snapshot后,都会向JobManager发送ACK,
当sink完成snapshot后,向JobManager发送ACK的同时向kafka进行pre-commit。

Phase 2: Commit
当JobManager接收到所有算子的ACK后,就会通知所有的算子这次checkpoint已经完成。
Sink接收到这个通知后, 就向kafka进行commit,正式把数据写入到kafka

不同阶段fail over的recovery举措 :

  • 1、 在pre-commit前fail over,系统恢复到最近的checkponit
  • 2、在pre-commit后,commit前fail over,系统恢复到刚完成pre-commit时的状态

Flink的two phase commit实现 — 抽象类TwoPhaseCommitSinkFunction

TwoPhaseCommitSinkFunction有4个方法 :

  1. beginTransaction()
     开启事务.创建一个临时文件.后续把原要写入到外部系统的数据写入到这个临时文件
  2. preCommit()
     flush并close这个文件,之后便不再往其中写数据.同时开启一个新的事务供下个checkponit使用
  3. commit()
    把pre-committed的临时文件移动到指定目录
  4. abort()
     删除掉pre-committed的临时文件
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值