幂等是什么
幂等操作执行一次与执行多次的效果相同,注意判定依据是“效果”而不是响应码或响应体完全一致。HTTP 里 GET、HEAD、PUT、DELETE 被定义为幂等方法,POST 通常不是,因此支付、下单、回调处理这类关键写操作需要额外设计幂等机制。在网络重试、消息重投、用户重复点击都无法避免的分布式环境里,幂等是让重试机制安全成立的前提。
HTTP 方法属性
| 方法 | 是否安全 | 是否幂等 | 说明 |
|---|---|---|---|
| GET/HEAD | 是 | 是 | 只读,可缓存可重试 |
| PUT | 否 | 是 | 整体替换,重复执行结果一致 |
| DELETE | 否 | 是 | 重复删除语义与删除一次相同 |
| PATCH | 否 | 视实现 | 合并式补丁幂等,数值累加式补丁不幂等 |
| POST | 否 | 否 | 需要业务侧幂等键去重 |
基本信息
| 幂等键 | 客户端生成的唯一请求标识,服务端据此去重并复现首次结果 |
|---|---|
| 状态机 | 用状态约束重复请求:已处理的单据再次收到相同指令直接返回 |
| 唯一约束 | 数据库唯一索引兜底,防止并发写入产生重复记录 |
| 有效期 | 幂等记录需设定保留时长与清理策略,长期保留会造成存储膨胀 |
| 适用对象 | 所有会被重试的写操作,包括对外接口与内部消息消费 |
典型使用场景
- 支付下单:客户端超时重试时保证不会生成两笔订单
- 第三方回调:对方重复推送同一笔结果,处理逻辑只生效一次
- 消息消费:至少一次投递下,消费端按消息键去重
- 定时补偿任务:任务重跑不会重复扣减或重复发放
- 批量导入:断点续传或重复上传同一批数据不产生重复记录
- 运维脚本:接口重试与手工重放不会放大业务影响
幂等处理要点
幂等处理要点
1. 接收请求,读取幂等键(请求头或业务字段)
2. 尝试插入幂等记录:键唯一索引冲突说明已在处理
3. 命中已有记录且状态为成功 → 直接返回首次结果
4. 未完成 → 返回处理中,由调用方按约定重试
5. 业务处理与幂等记录写入保持在同一事务或补偿范围内幂等与去重不是同一件事:幂等要求重复执行的结果可复现(含响应内容),去重只保证不产生第二条记录,通常仍不足以保证调用方拿到一致结果。
先加唯一索引就算完成幂等,是常见误解;并发下仍是先写库后判重的话,仍可能出现业务侧重复执行。