调用幂等性设计
网络抖动与自动重试会让同一个请求到达两次,如果服务端不识别重复,就会重复扣费、重复发信、重复写库。幂等键是通用解法:客户端为一次业务动作申请唯一键,服务端查键表决定是执行还是直接返回上次结果,键的保留期要覆盖整个重试窗口。
基本信息
| 适用范围 | 付费、发信、写库等带副作用的操作必须幂等 |
|---|---|
| 键来源 | 由服务端签发或按业务唯一标识生成,避免客户端可预测乱造 |
| 执行流转 | 查键表 → 未命中则执行并落库 → 命中则返回原结果 |
| 并发同键 | 加锁等待或返回处理中,不能让两个请求同时执行 |
| 保留期 | 至少覆盖重试窗口,常见 24 小时 |
典型使用场景
- 扣费与计费:重试不应产生第二笔账单
- 发送通知:同一事件重放时不重复打扰用户
- 下单与写入:超时后重试,服务端按幂等键返回首次结果
- 批量重放:按批次号与条目键做去重,补跑结果一致
- 外部回调:第三方重复投递同一事件时只处理一次
幂等键流程
幂等键流程
请求: POST /generate {idempotency_key: uuid}
1 查键表:已存在 → 直接返回原结果(可附原请求时间)
2 不存在 → 执行并把结果与键一起落库(同一事务)
3 并发同键 → 加锁等待,或返回处理中状态让客户端稍后再查
键保留期: 24h,覆盖重试窗口
# 键与结果必须同事务落库,否则会出现执行了但没记录操作类型与是否需要幂等
| 操作 | 是否需要 | 原因 |
|---|---|---|
| 读取查询 | 不需要 | 无副作用,重复执行安全 |
| 扣费与下单 | 必须 | 重复执行造成资金损失 |
| 发送通知 | 必须 | 重复发送打扰用户 |
| 写库更新 | 建议 | 重复写可能覆盖并发修改 |
| 外部回调处理 | 必须 | 对方会重复投递 |
幂等键由客户端随意生成且可预测时,攻击者可以复用别人的键来读取结果,键的生成与权限校验要一起设计。