幂等与去重是什么
幂等指同一操作执行一次与执行多次产生相同结果。在批量场景里,幂等是重试、断点续跑、至少一次投递、任务补跑这些机制能够安全成立的前提。实现手段包括声明式赋值(把状态设为目标值而不是做增量)、条件写入(只在状态符合预期时更新)、唯一索引与去重表、幂等键(客户端生成唯一标识,服务端识别重复请求)、以及任务级状态位。去重是幂等的一种实现路径:靠唯一标识识别重复任务并丢弃。
基本信息
| 实现方式 | 声明式赋值、条件写、唯一索引、幂等键、状态位 |
|---|---|
| 判据 | 同一请求重复提交不产生额外副作用 |
| 必需配套 | 并发下的原子判断:检查与写入必须一次完成 |
| 观测指标 | 重复提交次数、去重命中次数、状态冲突次数 |
典型使用场景
- 批量任务失败后只重跑失败集合
- 队列至少一次投递导致任务可能被重复消费
- 客户端请求超时后重试同一个写操作
- 定时任务可能因重入或补跑执行两次
- 数据写入需要避免重复计数或重复创建
幂等实现示例
幂等实现示例
systemctl enable --now app.service # 声明式:已启用时重复执行无副作用
# 条件写入:只在状态符合预期时更新,重复处理不会叠加
# UPDATE orders SET state='paid' WHERE id=:id AND state='pending';
# 唯一索引兜底:重复插入被数据库拒绝,而不是产生重复数据
# ALTER TABLE events ADD UNIQUE KEY uk_event(event_id);
# 幂等键:客户端生成唯一标识,服务端识别并丢弃重复请求
curl -sS -X POST -H "Idempotency-Key: $(uuidgen)" -d @payload.json https://api.example.com/v1/jobs幂等手段对比
| 手段 | 适用场景 | 注意点 |
|---|---|---|
| 声明式赋值 | 配置与服务状态 | 需要底层工具支持设置语义 |
| 条件写入 | 数据库记录的状态流转 | 判断与写入必须原子 |
| 唯一索引 | 防止重复插入 | 冲突时的行为要明确定义 |
| 幂等键 | 跨服务的请求去重 | 键需持久化并设置合理保留期 |
| 状态位 | 任务级去重 | 状态清理与重置策略要明确 |
先检查再执行在并发下并不安全:两个实例可能同时通过检查然后都执行。要么把判断与写入合并成一次原子操作,要么用唯一约束在最后一道关口兜底。
幂等键的保留期应长于客户端的最大重试窗口。键过早过期会让迟到的重试被当作新请求处理,重复执行重新出现,而且这种问题难以复现。