flink checkpoint 恢复_Flink端到端Exactly-once

fb058f03f92e5f155bce4c9e874adb6b.png

Exactly-once语义

Flink自1.4.0开始实现exactly-once的数据保证,即在任何情况下都能保证数据对应用产生的效果只有一次,不会多也不会少。具体实现依赖于抽象类TwoPhaseCommitSinkFunction,用户只需要实现类接口就可以自己定义对外部系统的exactly-once。

Flink的checkpoint可以保证作业失败的情况下从最近一次快照进行恢复,也就是可以保证系统内部的exactly-once。但是,flink有很多外接系统,比如将数据写到kafka,一旦作业失败重启,offset重置,会消费旧数据,从而将重复的结果写到kafka。如下图:

e4dfff92cdce7d10e2e28944415dd95a.png

这个时候,仅靠系统本身是无法保证exactly-once的。系统之间的数据一致性一般要靠2PC协议来保证,flink的TwoPhaseCommitSinkFunction也是基于此实现的。exactly-once的语义如下图:

ec6b41dc7e571c36da9599e8e21dd620.png

Exactly-once VS At-least-once

算子做快照时,如果等所有输入端的barrier都到了才开始做快照,那么就可以保证算子的exactly-once;如果为了降低延时而跳过对其,从而继续处理数据,那么等barrier都到齐后做快照就是at-least-once了,因为这次的快照掺杂了下一次快照的数据,当作业失败恢复的时候,这些数据会重复作用系统,就好像这些数据被消费了两遍。

注:对齐只会发生在算子的上端是join操作以及上游存在partition或者shuffle的情况,对于直连操作类似map、flatMap、filter等还是会保证exactly-once的语义。

端到端的Exactly once实现

下面以一个简单的flink读写kafka作为例子来说明(kafka0.11版本开始支持exactly-once语义)。如图所示:

c1c82e3601929f5eb249a1fb29300da7.png

上图由kafka source、window操作和kafka sink组成。

为了保证exactly-once语义,作业必须在一次事务中将缓存的数据全部写入kafka。一次commit会提交两个checkpoint之间所有的数据。

pre-commit阶段起始于一次快照的开始,即master节点将checkpoint的barrier注入source端,barrier随着数据向下流动直到sink端。barrier每到一个算子,都会出发算子做本地快照。如下图所示:

602be41553d1a15fe9ec49eec29861f2.png

当状态涉及到外部系统时,需要外部系统支持事务操作来配合flink实现2PC协议,从而保证数据的exatly-once。这个时候,sink算子出了将自己的state写到后段,还必须准备好事务提交。

76424531ba42484cbd65eed28c7af27c.png

当所有的算子都做完了本地快照并且回复到master节点时,pre-commit阶段才算结束。这个时候,checkpoint已经成功,并且包含了外部系统的状态。如果作业失败,可以进行恢复。

接下来是通知所有的算子这次checkpoint成功了,即2PC的commit阶段。source节点和window节点没有外部状态,所以这时它们不需要做任何操作。而对于sink节点,需要commit这次事务,将数据写到外部系统。

fcad4deaaa313774380c39cf27bc4722.png

总的来说,流程如下:

  • 一旦所有的算子完成了它们的pre-commit,它们会要求一个commit。
  • 如果存在一个算子pre-commit失败了,本次事务失败,我们回滚到上次的checkpoint。
  • 一旦master做出了commit的决定,那么这个commit必须得到执行,就算宕机恢复也有继续执行。

实现flink的2PC

由于2PC协议比较复杂,所以flink对它做了抽象,即TwoPhaseCommitSinkFunction。可以通过以下四步实现:

  • beginTransaction。开始一次事务,在目的文件系统创建一个临时文件。接下来我们就可以将数据写到这个文件。
  • preCommit。在这个阶段,将文件flush掉,同时重起一个文件写入,作为下一次事务的开始。
  • commit。这个阶段,将文件写到真正的目的目录。值得注意的是,这会增加数据可视的延时。
  • abort。如果回滚,那么删除临时文件。

如果pre-commit成功了但是commit没有到达算子旧宕机了,flink会将算子恢复到pre-commit时的状态,然后继续commit。我们需要做的还有就是保证commit的幂等性,这可以通过检查临时文件是否还在来实现。

总结

  • Flink依托checkpoint来实现端到端的一致性语义。
  • 这种方法的优势是不需要持久化传输中的数据,没有必要将每个阶段的计算都写到磁盘。
  • Flink抽象了TwoPhaseCommitSinkFunction来帮助用户更好地实现exactly-once语义。
  • 自Flink 1.4.0,Pravega和Kafka 0.11都支持了exactly-once语义。
  • Kafka 0.11在TwoPhaseCommitSinkFunction实现了事务支持,并且开销很小。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值