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
参考文献#
作者:koktlzz
出处:https://www.cnblogs.com/koktlzz/p/14629654.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现