Kafka:事务

Kafka引入事务以实现:

  • 跨会话或跨Partition的Exactly-Once:Producer将消息发送到多个Topic/Partition时,可以封装在一个事务中,形成一个原子操作:多条消息要么都发送成功,要么都发送失败。所谓的失败是指消息对事务型Consumer不可见,而Consumer只读取成功提交事务(Committed)的消息。
  • consume-process-produce场景的Exactly-Once:所谓consume-process-produce场景,是指Kafka Stream从若干源Topic消费数据,经处理后再发送到目标Topic中。Kafka可以将整个流程全部封装在一个事务中,并维护其原子性:要么源Topic中的数据被消费掉且处理后的结果正确写入了目标topic,要么数据完全没被处理,还能从源Topic里读取到。

事务无法实现跨系统的Exactly-Once:如果数据源和目的地不只是Kafka的Topic(如各种数据库),那么操作的原子性便无法保证。

启用事务#

  • 对于Producer,需将transactional.id参数设置为非空,并将enable.idempotence参数设置为true
  • 对于Consumer,需将isolation.level参数设置为read_committed,即Consumer只消费已提交事务的消息。除此之外,还需要设置enable.auto.commit参数为false来让Consumer停止自动提交Offset。

Producer事务#

Kafka将事务状态存储在内部的topic:__transaction_state中,并由Transaction Coordinator组件维护。每个事务型Producer都拥有唯一标识Transaction ID,它与ProducerID相绑定。Producer重启后会向Transaction Coordinator发送请求,根据Transaction ID找到原来的ProducerID以及事务状态。

另外,为了拒绝僵尸实例(Zombie Instance),每个Producer还会被分配一个递增的版本号Epoch。Kafka会检查提交事务的Proudcer的Epoch,若不为最新版本则拒绝该实例的请求。

在分布式系统中,一个instance的宕机或失联,集群往往会自动启动一个新的实例来代替它的工作。此时若原实例恢复了,那么集群中就产生了两个具有相同职责的实例,此时前一个instance就被称为“僵尸实例(Zombie Instance)”。

Consumer事务#

两种方案:
读取消息 -> 更新(提交Offset -> 处理消息:若处理消息时发生故障,接管的Consumer从更新后的Offset读数据,则缺数据,类似于At Most Once
读取消息 -> 处理消息 -> 更新(提交)Offset:若更新Offset时发生故障,接管的Consumer重新读之前的数据,数据重复,类似于At Least Once
选取第二种方案,因为只要在消息中添加唯一主键,便可以让第二次写入的数据覆盖重复数据,从而做到Exactly-Once

参考文献#

Transactions in Apache Kafka

posted @   koktlzz  阅读(563)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示
主题色彩