如何保证消息可靠投递?生产端 confirm 与事务机制怎么选?

结论先行:消息可靠投递要分三段保障:生产端到 Broker、Broker 端存储、Broker 到消费端。生产端主要靠 confirm 确认机制或事务机制,消费端靠手动 ack 与幂等。可靠投递只解决"不丢",不解决"不重",因此最终都要配合消费幂等与对账补偿兜底。

一、三段可靠性模型

阶段丢失原因保障手段
生产 → Broker网络异常、Broker 拒收confirm/ack 确认、事务、失败重试
Broker 存储宕机丢内存数据持久化、主从/多副本
Broker → 消费消费者宕机未 ack手动 ack、重投、死信兜底

二、生产端两种机制对比(RabbitMQ 为例)

机制原理优缺点
confirm(发布确认)消息到达交换机/队列后异步回调 ack/nack异步、吞吐高,推荐
事务(txSelect)每条消息提交事务,同步等结果吞吐极低,生产基本不用
本地消息表业务与消息同库事务,定时任务补投与具体 MQ 无关,通用兜底

三、常见做法示例

# RabbitMQ 生产者开启发布确认(channel 级)
channel.confirmSelect();
channel.basicPublish("", "q.order", null, body);
if (!channel.waitForConfirms()) {
    // 未确认:记录日志,走重试或补偿
}
  • 补充:Kafka 生产端对应 acks=all + retries + 幂等生产者,保证发送不丢且不因重试乱序;
  • 最终兜底:核心消息在业务库建消息表,与业务操作同一本地事务写入,后台任务扫描未确认消息重新投递;
  • 监控指标:关注发送失败率、confirm 超时数、消费堆积量与重投次数,异常要早于用户投诉被发现;
  • 对账口径:以业务单据为核心定期核对 MQ 侧与业务侧的完成状态,发现缺口补投消息。

常见追问 / 记忆点

  • 追问:confirm 与事务能同时用吗?答:不能,二者互斥,confirm 是异步机制性能远优于事务。
  • 追问:可靠投递等于不重复吗?答:不等于,投递保证通常是至少一次,重复消费要靠幂等设计解决。
  • 追问:消息一直投递失败怎么办?答:超过重试次数进入死信队列或告警,由人工/补偿任务处理。
  • 记忆点:生产 confirm、存储持久化、消费手动 ack,三管齐下再补幂等与对账。
笔记加载中…