前端请求中的幂等键有什么作用?哪些接口需要 Idempotency-Key?
简化版
幂等键是客户端为一次业务操作生成的唯一标识,例如 Idempotency-Key。当网络超时、用户重复点击或客户端重试时,服务端可以根据这个 key 判断是否已经处理过,避免重复创建订单、重复扣款或重复提交。前端负责为同一次业务动作稳定生成和传递 key,服务端负责存储、校验和返回同一结果。它主要用于写接口,不是 GET 缓存。
详细版
幂等键常用于有副作用的接口。
| 场景 | 是否需要 | 原因 |
|---|---|---|
| 创建订单 | 需要 | 防重复创建 |
| 支付确认 | 需要 | 防重复扣款 |
| 表单提交 | 常需要 | 防重复写入 |
| 查询列表 | 通常不需要 | GET 天然更易重试 |
fetch('/api/orders', {
method: 'POST',
headers: { 'Idempotency-Key': draftId },
body: JSON.stringify(payload)
})
幂等键的关键是“同一次业务动作同一个 key,不同业务动作不同 key”。
完整版教学
一、为什么需要幂等键
写接口最怕“不知道成功还是失败”。用户提交订单后网络超时,前端没收到响应,但服务端可能已经创建成功。
如果前端直接重试,又没有幂等保护,就可能创建两笔订单。
二、前端防重复不够
按钮 disabled、防抖、loading 状态都只能减少正常用户重复操作。攻击者、刷新、重试、代理层重放和移动网络抖动都可能绕过前端状态。
所以写接口安全要靠服务端幂等,前端只是配合传 key。
三、key 如何生成
key 可以来自业务草稿 id、订单草稿 id,也可以由前端生成 UUID。
const key = crypto.randomUUID()
同一次业务动作要复用同一个 key。用户重新创建一张新订单时,要生成新 key。
四、服务端如何处理
服务端收到 key 后,会记录 key、请求摘要、处理状态和结果。重复请求命中同一个 key 时,返回第一次处理结果。
| 服务端记录 | 作用 |
|---|---|
| key | 去重 |
| request hash | 防同 key 不同参数 |
| status | 判断处理中还是已完成 |
| response | 重复请求返回一致结果 |
五、前端如何保存 key
如果只是一次点击流程,key 可以存在内存状态里。如果刷新后还要恢复提交状态,可以存在 sessionStorage 或业务草稿中。
但不要长期复用同一个 key,否则新的业务动作会被错误当成重复请求。
六、和请求重试的关系
只有有幂等键的写请求,前端才更敢在超时后重试。否则超时后应先查询业务结果,再决定下一步。
GET 查询通常天然可重试,但也要注意服务端是否真的没有副作用。
七、常见误区与追问
- 误区:幂等键由前端实现就够。 前端只负责传 key,真正去重要在服务端。
- 误区:每次重试都生成新 key。 这样服务端会认为是新操作,幂等失效。
- 误区:同一个 key 可以一直复用。 不同业务动作必须使用不同 key。
- 追问:同 key 但参数不同怎么办? 服务端应比对请求摘要,拒绝或报警。
- 追问:幂等记录保存多久? 取决于业务风险和重试窗口,常按分钟、小时或天设置 TTL。
- 追问:前端超时后怎么处理? 有幂等键可重试或查询结果,无幂等键应谨慎避免重复写入。
八、加强记忆
幂等键记成“这次操作的身份证”。同一次操作同一个 key,重试不重复;新操作新 key,不混淆。前端发证件,服务端查证件。