幂等与去重
消息重复投递、Idempotency-Key。
30 分钟
幂等与去重
消息与 HTTP 在分布式环境里常 至少投递一次:网络超时重试、Consumer rebalance 重复消费,会导致 重复扣库存、重复发券。幂等 保证「同一业务操作执行多次,效果等同一次」。
学习目标
- 理解 at-least-once 与幂等消费的关系
- 掌握 Idempotency-Key 与业务去重表
- 串联 kafka-delivery 与 Saga(ip-saga)
重复从何而来
Producer ──send──► Broker ──deliver──► Consumer 处理 OK ──ack 丢失──►
Broker 重投 ──► 再次处理 ⚠
HTTP 同理:客户端 POST 超时重试,服务端可能收到两次。rmq-reliability 讲 ack 与 nack。
HTTP:Idempotency-Key
POST /orders
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
服务端:
- 查
idempotency_keys表:key 已存在 → 返回 同一响应,不重复下单 - 不存在 → 执行业务 + 存 key 与响应快照
GET/PUT/DELETE 天然较幂等;POST 创建资源 必须 显式设计。
消息:消费端去重
| 策略 | 做法 |
|---|---|
| 自然幂等 | UPDATE stock SET n=n-1 WHERE id=? 带条件 |
| 业务幂等表 | processed_events(messageId) 插入成功才处理 |
| Redis SETNX | 短 TTL 去重(需持久化场景慎用) |
ip-event-driven Outbox Relay 也要保证 同 eventId 不重复 publish 或 Consumer 可去重。
Saga 中的幂等
InventoryReserved(orderId=1) 第 1 次 → 扣库存
InventoryReserved(orderId=1) 第 2 次 → 检测已 reserved,跳过
CompensateRelease(orderId=1) 第 2 次 → 检测已 release,跳过
补偿步骤同样必须幂等,否则重试会 多释库存。
与 exactly-once 幻想
Kafka 事务 + 幂等 Producer 降低重复,跨服务仍按 at-least-once + 幂等消费 设计最稳(kafka-producer)。
练习
- 为 Consumer 设计 messageId 去重表字段