用途:在编写任何会改变状态的操作前,先问“同样的输入再跑一次会怎样”。重复来源有三类,且都属于正常运行而非边缘情况:用户重试(双击、刷新、后退再提交)、网络重试(操作成功但响应丢失)、基础设施重投递(Webhook 超时重试、消息队列至少一次投递、定时任务重叠)。
主要能力:区分天然幂等与非幂等操作。天然幂等如 SET x = 5、UPDATE status='paid' WHERE id=?、DELETE WHERE id=?、PUT /users/123、Upsert;非幂等如 SET x = x + 1、INSERT INTO orders、balance += amount、POST /orders、sendEmail、stripe.charges.create。优先设计为天然幂等,即“设为某状态”而非“施加某变更”。
检测信号:无幂等键的 POST 创建记录;重试逻辑包裹非幂等调用;未记录已处理事件 ID 的 Webhook 处理器;使用 INCREMENT 或 INSERT 而无去重的队列消费者;无去重检查的通知调用;早期步骤有副作用的多步操作。
使用方式:API 端点用幂等键,客户端生成 UUID 随请求发送,服务端据此识别重试;幂等记录须与业务数据在同一事务中创建,外部副作用使用派生自原键的独立键,重复请求回放已存响应。Webhook 用事件 ID 去重,唯一约束可捕获并发投递竞争,非事务性副作用放在去重门之后。队列消费者用生产者提供的唯一事务 ID,在同一事务中记录,真实错误时不 ack 让队列重投。外部 API 尽量传幂等键,不支持时自行记录调用。
限制与关联陷阱:幂等检查本身存在竞态,去重记录必须与业务操作原子创建;去重检查须读主库,副本延迟会漏判;重试非幂等操作会放大负载,幂等加重试风暴等于规模化数据损坏。