跳到正文

消息队列、幂等与一致性 ​

  • 状态:未准备
  • 适用方向:Go 全栈 / Go 后端
  • 最近复习:待填写
  • 下次复习:待安排

一句话回答 ​

消息队列解耦生产与消费、吸收有限峰值,同时引入重复、延迟和失败恢复;至少一次投递要靠业务幂等,跨数据库与队列的一致性需单独设计。

原理解释 ​

先提交 offset 再处理,崩溃可能丢业务;先处理再提交,崩溃可能重复。用稳定业务 ID,加唯一约束或状态条件更新,让重复投递不重复产生效果;去重记录与业务变更尽量处于同一数据库事务。

Kafka 分区内日志有序,不保证跨分区全局有序。相同 key 的分区策略有助于局部顺序,但消费者并发、重试、分区变化与外部推送仍可能影响最终可见顺序。生产者幂等或 Kafka 事务不自动涵盖外部 MySQL、HTTP 和 WebSocket 副作用。

数据库提交后发消息,进程可能在两者之间崩溃;先发消息再提交,又可能消费到未成立的业务。Outbox 将业务变更与待发事件写入同一数据库事务,再由 relay 重试发布;发布与标记之间仍可能重复,消费者依然要幂等。

场景与边界 ​

队列不是无限容量。消费积压时监测 lag、处理耗时、失败率和最老消息年龄;失败消息要有限重试、退避和人工恢复入口,避免毒消息无限阻塞。关键事件需要持久化与确认,在线实时推送允许丢失时也需说明历史补拉路径。

项目中的应用 ​

EinoTalk 双入口与 dispatcher是复用逻辑的入口。现有材料说明落库失败只记录日志、节点 Pub/Sub 无持久化,不能讲成端到端恰好一次或推送落库原子一致。Outbox 是可讨论方案,未确认已实现。

常见追问 ​

  • 消息 ID 能保证幂等吗? 还需原子地约束执行结果,先查后写存在竞态。
  • 如何重试? 区分瞬时与永久错误,有退避、次数上限、重试预算和可观测记录。
  • 同会话 key 就严格保序? 只覆盖部分环节,还需核对消费、重试和客户端处理。

参考资料 ​

理解机制,讲清取舍,用复盘检验掌握。