分布式消息投递模型快速上手

张开发
2026/4/8 10:09:33 15 分钟阅读

分享文章

分布式消息投递模型快速上手
文章目录1.三种投递模型2.至少一次投递详解2.1 工作原理2.2 优缺点2.3 典型应用场景3.三种模型的实现原理3.1 至多一次 (At Most Once)3.2 至少一次 (At Least Once)3.3 恰好一次 (Exactly Once)4.主流消息队列的投递保证5.实际开发中的选择策略6.总结参考文献在分布式消息系统中投递模型定义了消息从生产者发送到消费者接收的可靠性保证。其中“至少一次投递”是最常用、也是理解其他模型的基础。1.三种投递模型模型英文含义可能情况至多一次At Most Once消息可能丢失但绝不会重复丢消息 ✅ / 不丢 ❌ / 重复 ❌至少一次At Least Once消息不会丢失但可能重复丢消息 ❌ / 不丢 ✅ / 重复 ✅恰好一次Exactly Once消息既不丢失也不重复丢消息 ❌ / 不丢 ✅ / 重复 ❌在分布式系统中Exactly Once 通常是由“至少一次 幂等消费”组合实现的理想状态而不是单一机制能保证的。2.至少一次投递详解2.1 工作原理消费者消息队列生产者消费者消息队列生产者如果消费者 ACK 丢失网络超时等发送消息 M返回 ACK (确认收到)拉取消息返回消息 M处理完成返回 ACK标记消息已消费重新投递消息 M (可能重复)核心机制生产者端消息队列确认收到后才算成功否则重发消费者端必须主动发送 ACK 确认队列才认为消费完成重试机制如果超时或收到错误队列会重新投递2.2 优缺点优点缺点✅ 消息不会丢失可靠性高❌ 可能收到重复消息✅ 实现相对简单❌ 消费者必须实现幂等性✅ 大多数消息队列默认支持❌ 重复消息可能影响业务逻辑2.3 典型应用场景场景原因订单支付通知支付成功消息绝对不能丢重复可通过业务去重日志采集宁可重复采集也不能丢失重要日志数据同步数据可以重复同步通过版本号去重异步任务任务可以重复执行需幂等设计3.三种模型的实现原理3.1 至多一次 (At Most Once)发送消息直接投递无需 ACK消息可能丢失生产者消息队列消费者丢弃实现方式生产者不等待确认fire-and-forget消费者不发送 ACK消息队列收到即丢弃不持久化适用场景监控指标上报、实时视频流、可容忍丢失的日志3.2 至少一次 (At Least Once)实现方式生产者同步发送 重试机制等待队列 ACK消息队列消息持久化到磁盘等待消费者 ACK 后才删除消费者处理完成后发送 ACK如果超时或失败队列重新投递关键配置以 Kafka 为例# 生产者等待所有副本确认 acksall retries3 # 消费者手动提交 offset enable.auto.commitfalse3.3 恰好一次 (Exactly Once)实现方式通常是“至少一次” “幂等消费”的组合。确保确保至少一次投递消息不丢幂等消费消息不重恰好一次技术方案方案说明代表系统分布式事务2PC / 3PC 协议传统数据库事务消息消息队列内置事务RocketMQ、Kafka 事务幂等设计业务层去重更常用数据库唯一键、Redis 去重去重表消费者记录处理过的消息 ID自定义实现4.主流消息队列的投递保证消息队列默认模型支持的模型说明Kafka至少一次至多一次、恰好一次事务通过 acks 和 enable.auto.commit 配置RocketMQ至少一次至多一次、恰好一次同步刷盘 同步复制保证不丢RabbitMQ至少一次至多一次通过 publisher confirms consumer ackPulsar至少一次至多一次、恰好一次支持 Exactly Once 语义AWS SQS至少一次—FIFO 队列支持 Exactly Once5.实际开发中的选择策略可以不可以可以不可以业务需求消息可以丢失吗至多一次可以容忍重复吗至少一次 业务去重恰好一次幂等 事务/去重表日志、监控订单、支付金融、对账业务类型推荐模型理由金融交易恰好一次数据绝对准确不能丢不能重订单支付至少一次 幂等不能丢重复可通过订单号去重日志采集至多一次丢几条日志可接受性能优先用户行为分析至少一次宁可重复统计不能丢数据6.总结模型核心保证实现代价典型场景至多一次不重复可能丢最低监控、实时视频至少一次不丢失可能重复中等大多数业务场景恰好一次不丢不重最高金融、对账一句话总结“至少一次”意味着“消息绝对不会丢但你可能会收到多次”——所以消费者的幂等处理是标配。如果你能做到“至少一次 幂等”就等价于实现了“恰好一次”。参考文献AMQP: HomeKafka 协议规范

更多文章