Kafka 原子更新,精确一次消费 Exactly-Once --------- 学习笔记

目录

原子更新

精确一次消费

写入幂等

事务消息

总结


原子更新

Kafka 如何实现原子更新?即操作要么完全成功、要么完全失败,无中间状态。核心结论是:Kafka 本身不直接提供 "更新" 语义,但可通过原子写入 + 消费语义 + 外部协调实现业务层面的原子更新。

Kafka 的生产者写入是原子性的,一条消息要么持久化成功,要么失败。支持消息生产者写入幂等和事务消息,保证消息 "仅一次交付",避免重复写入。Kafka 消费者手动提交位移 offset 是原子提交,原子更新,确保消费状态不丢失、不重复。

方案:

生产端:Producer 中要么消息必须带 key,让同类型业务消息绑定到指定的分区;或是由 Key + 分区器共同决定;或是使用事务消息。

消费端:简单场景消费者手动 commitSync(业务层使用唯一 id 或是 使用版本号)。复杂场景消费也需要用到"事务型消费",把消费操作放在一个数据库事务里,保存 offset 到数据库,执行完消费操作再手动提交 offset 到 Brocker。消费业务层面必须做幂等。

精确一次消费

在分布式场景下,消息传递通常会面临三种语义:

At-Most-Once(最多一次):消息可能丢失, but 不会重复消费,适用于非核心场景(如日志采集);

At-Least-Once(至少一次):消息不会丢失, but 可能重复消费,是Kafka默认的语义,可以结合消息id 和 Redis 过滤解决重复消费问题;

Exactly-Once(精确一次):消息既不丢失,也不重复消费,是金融、订单等核心业务的刚需。

其中:幂等性仅保证单生产者单分区的 "仅一次写入",事务消息可实现跨分区 / 跨主题的原子写入;

写入幂等

因为 Kafka 生产者启动时会从 Broker 获取到一个 PID,它发送消息时会根据 路由键 key 路由到某个主题下的某一个分区。写入时从分区中获得下一个 Sequence Number 序列号,然后分区写入时比对 pid,seq 是否已存在,已存在 seq 就是重复消息,丢弃,如果发现 seq 就是最新消息位置 pos+1,那就写入;所以开启 enable.idempotence = true 幂等特性,幂等性保证单生产者单分区的 "仅一次写入"。

事务消息

Kafka 事务消息依赖Transaction Coordinator(事务协调器)和Transaction Log(事务日志)来实现,事务协调器负责管理事务的生命周期(开始、提交、回滚),事务日志负责持久化存储,避免宕机丢失。

Producer 启动事务前会和 Transaction Coordinator 建立连接,然后 Producer 生产者调用 beginTransaction()方法,向事务协调器发送"启动事务"请求; 事务协调器生成唯一的 Transaction ID(事务ID),并将事务状态标记为"BEGIN",记录到事务日志。

Producer 向多个 Partition 发送消息(可跨 Partition),发送时携带 Transaction ID 和 PID;Broker 接收消息后,不会立即将消息置为"可消费"状态,而是标记为"事务未提交",暂时隐藏,Consumer 无法拉取 。

Producer确认所有消息都已成功发送到Broker(收到所有ack),调用commitTransaction()方法,向Transaction Coordinator发送"提交事务"请求;Transaction Coordinator收到请求后,先检查该事务下的所有消息是否都已成功持久化;若全部持久化成功,将事务状态标记为"COMMITTED",并向所有相关Broker发送"提交确认";Broker收到确认后,将"事务未提交"的消息置为"可消费"状态,Consumer可正常拉取消费。

若发送过程中出现异常(如部分消息发送失败、Producer宕机),Producer调用abortTransaction()方法,向Transaction Coordinator发送"回滚事务"请求;

Transaction Coordinator将事务状态标记为"ABORTED",并向所有相关Broker发送"回滚确认";

Broker收到确认后,删除"事务未提交"的消息,不会让Consumer拉取,实现事务回滚。

总结

1,开启幂等性,enable.idempotence = true。

2,启用事务消息,配置 transactional.id=xxx ,全局唯一,建议和 Producer 实例绑定;同时开启幂等性;设置 isolation.level=read_committed 只消费已提交的事务消息,避免消费未提交的消息;

3,消息确认机制,设置 acks=all(所有副本确认),确保消息真正持久化,避免 Broker宕机导致消息丢失;

相关推荐
AnalogElectronic20 分钟前
uniapp学习5,兼容微信小程序的俄罗斯方块游戏
学习·微信小程序·uni-app
知识分享小能手22 分钟前
MongoDB入门学习教程,从入门到精通,MongoDB应用程序设计知识点梳理(9)
数据库·学习·mongodb
雷工笔记44 分钟前
读书笔记《工程师进阶之路》
笔记·学习
智算菩萨1 小时前
【论文精读】通过元学习与关联规则挖掘增强人工智能在网络安全领域特征选择中的可解释性
论文阅读·人工智能·学习·web安全·论文笔记
Engineer邓祥浩1 小时前
JVM学习笔记(4) 第二部分 自动内存管理 第3章 垃圾收集器与分配策略
jvm·笔记·学习
VelinX1 小时前
【个人学习||ai提示词工程】01Prompt Engineering
学习
传感器与混合集成电路1 小时前
面向储气库注采井的分布式光纤监测技术
分布式
chase。2 小时前
【学习笔记】基于扩散模型的运动规划学习与适应
人工智能·笔记·学习
321.。2 小时前
Linux 进程控制深度解析:从创建到替换的完整指南
linux·开发语言·c++·学习
ZTLJQ2 小时前
任务调度的艺术:Python分布式任务系统完全解析
开发语言·分布式·python