kafka两阶段提交、幂等以及flink结合

1 在checkpoint之间是一直begin_transaction,之后开始checkpoint后是pre_commit, 数据写入kafka broker, 同时在transaction协调器以及 消费者处理器之间写入本次事务的元信息;等到本次从source到sink之间的checkpoint全部完成,job manager完成checkpoint时,sink的producer才正式发出事务commit,这时候kafka之前写入broker的log才会对消费者显示有效可以读取。

以下信息取自:https://zhuanlan.zhihu.com/p/111304281

具体代码层面:

flink kafkasink的TwoPhaseCommitSinkFunction仍然留了以下四个抽象方法待子类来实现:

beginTransaction():开始一个事务,返回事务信息的句柄。

preCommit():预提交(即提交请求)阶段的逻辑。

commit():正式提交阶段的逻辑。

abort():取消事务

这四个方法实际上是flink对于sink端支持两阶段事务提交中间件的抽象,具体针对kafka sink来说,应用了kafka对应的两阶段提交的方法。

1.1 预提交阶段

FlinkKafkaProducer011.preCommit()方法的实现很简单。其中的flush()方法实际上是代理了KafkaProducer.flush()方法。

那么preCommit()方法是在哪里使用的呢?答案是TwoPhaseCommitSinkFunction.snapshotState()方法。从前面的类图可以得知,TwoPhaseCommitSinkFunction也继承了CheckpointedFunction接口,所以2PC是与检查点机制一同发挥作用的。

每当需要做checkpoint时,JobManager就在数据流中打入一个屏障(barrier),作为检查点的界限。屏障随着算子链向下游传递,每到达一个算子都会触发将状态快照写入状态后端(state BackEnd)的动作。当屏障到达Kafka sink后,触发preCommit(实际上是KafkaProducer.flush())方法刷写消息数据,但还未真正提交。接下来还是需要通过检查点来触发提交阶段。

1.2 提交阶段

FlinkKafkaProducer011.commit()方法实际上是代理了KafkaProducer.commitTransaction()方法,正式向Kafka提交事务。

该方法的调用点位于TwoPhaseCommitSinkFunction.notifyCheckpointComplete()方法中。顾名思义,当所有检查点都成功完成之后,会回调这个方法。

该方法每次从正在等待提交的事务句柄中取出一个,校验它的检查点ID,并调用commit()方法提交之。

1.3 回退阶段

可见,只有在所有检查点都成功完成这个前提下,写入才会成功。这符合前文所述2PC的流程,其中JobManager为协调者,各个算子为参与者(不过只有sink一个参与者会执行提交)。一旦有检查点失败,notifyCheckpointComplete()方法就不会执行。如果重试也不成功的话,最终会调用abort()方法回滚事务。
 

普遍意义上flink的两阶段提交是这样的:

Let’s discuss how to extend a `TwoPhaseCommitSinkFunction` on a simple file-based example. We need to implement only four functions and present their implementations for an exactly-once file sink:

  1. beginTransaction - to begin the transaction, we create a temporary file in a temporary directory on our destination file system. Subsequently, we can write data to this file as we process it.
  2. preCommit - on pre-commit, we flush the file, close it, and never write to it again. We’ll also start a new transaction for any subsequent writes that belong to the next checkpoint.
  3. commit - on commit, we atomically move the pre-committed file to the actual destination directory. Please note that this increases the latency in the visibility of the output data.
  4. abort - on abort, we delete the temporary file.

 

2 kafka的幂等性可以防止重复提交。每个producer可以用户显式的指定transactionId, 这样producer Id以及topic、partition和生产者发送的每条消息的递增的seq Id.这些可以唯一确定一条消息,相当于唯一键,防止broker内部数据重复写入。

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flink阶段提交是指在实现EXACTLY_ONCE语义时使用的一种协议。在Flink中,使用TwoPhaseCommitSinkFunction接口来实现阶段提交。\[1\]具体实现中,FlinkKafkaProducer.commit()方法代理了KafkaProducer.commitTransaction()方法,用于向Kafka提交事务。\[2\]这样可以确保在发生故障或者异常情况下,能够保证数据的一致性和可靠性。 通过使用阶段提交协议,Flink能够实现对外部Kafka Sink的EXACTLY_ONCE语义。这在Flink 1.4.0版本中引入了TwoPhaseCommitSinkFunction接口,并在Kafka Producer的connector中实现了它。\[3\]同时,Kafka幂等性和事务也对实现EXACTLY_ONCE语义起到了重要的作用。 总结来说,Flink阶段提交是通过使用TwoPhaseCommitSinkFunction接口和Kafka Producer的commitTransaction()方法来实现的,以确保对外部Kafka Sink的EXACTLY_ONCE语义。 #### 引用[.reference_title] - *1* *3* [Flink阶段提交](https://blog.csdn.net/lisenyeahyeah/article/details/90288231)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Flink阶段提交](https://blog.csdn.net/liuwei0376/article/details/126259056)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值