外观
消息队列、幂等与一致性
- 状态:未准备
- 适用方向:Go 全栈 / Go 后端
- 最近复习:待填写
- 下次复习:待安排
一句话回答
消息队列解耦生产与消费、吸收有限峰值,同时引入重复、延迟和失败恢复;至少一次投递要靠业务幂等,跨数据库与队列的一致性需单独设计。
原理解释
先提交 offset 再处理,崩溃可能丢业务;先处理再提交,崩溃可能重复。用稳定业务 ID,加唯一约束或状态条件更新,让重复投递不重复产生效果;去重记录与业务变更尽量处于同一数据库事务。
Kafka 分区内日志有序,不保证跨分区全局有序。相同 key 的分区策略有助于局部顺序,但消费者并发、重试、分区变化与外部推送仍可能影响最终可见顺序。生产者幂等或 Kafka 事务不自动涵盖外部 MySQL、HTTP 和 WebSocket 副作用。
数据库提交后发消息,进程可能在两者之间崩溃;先发消息再提交,又可能消费到未成立的业务。Outbox 将业务变更与待发事件写入同一数据库事务,再由 relay 重试发布;发布与标记之间仍可能重复,消费者依然要幂等。
场景与边界
队列不是无限容量。消费积压时监测 lag、处理耗时、失败率和最老消息年龄;失败消息要有限重试、退避和人工恢复入口,避免毒消息无限阻塞。关键事件需要持久化与确认,在线实时推送允许丢失时也需说明历史补拉路径。
项目中的应用
EinoTalk 双入口与 dispatcher是复用逻辑的入口。现有材料说明落库失败只记录日志、节点 Pub/Sub 无持久化,不能讲成端到端恰好一次或推送落库原子一致。Outbox 是可讨论方案,未确认已实现。
常见追问
- 消息 ID 能保证幂等吗? 还需原子地约束执行结果,先查后写存在竞态。
- 如何重试? 区分瞬时与永久错误,有退避、次数上限、重试预算和可观测记录。
- 同会话 key 就严格保序? 只覆盖部分环节,还需核对消费、重试和客户端处理。