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宕机导致消息丢失;

相关推荐
祁鱼鱼鱼鱼鱼2 小时前
Keepalived高可用学习总结及实验复现
学习
Coovally AI模型快速验证2 小时前
仅凭单目相机实现3D锥桶定位?UNet-RKNet破解自动驾驶锥桶检测难题
数码相机·学习·yolo·目标检测·3d·目标跟踪·自动驾驶
观书喜夜长2 小时前
XSS 入门实战:反射型、存储型、DOM 型原理与防御(DVWA 靶场)
学习·web安全
詩不诉卿2 小时前
Zephyr学习之mcuboot的最简单使用记录
学习
MOON404☾2 小时前
R语言EDA学习笔记
笔记·学习·数据分析·r语言·eda
Coder_Boy_2 小时前
从Java虚拟机到分布式中间件:高并发体系全解析(含电商实践细节)
java·jvm·分布式·spring·中间件
Shining05962 小时前
CPU 并行编程系列《CPU 性能优化导论》
人工智能·学习·其他·性能优化·infinitensor
sealaugh322 小时前
react native(学习笔记第一课)环境构筑(hello,world)
笔记·学习·react native