首页/数据/NoSQL 速查/幂等设计:去重键与唯一索引
选型与架构50 条

幂等设计:去重键与唯一索引

至少一次投递、用户重复点击、网络重试都会带来重复请求。幂等实现分两层:请求层用幂等键加唯一索引拦截重复提交;数据层用 upsert 与版本条件让重复执行不产生额外副作用。两层结合才能覆盖乱序与并发。

NoSQL 速查数据更新于 2026-10-12

唯一索引拦截重复提交(MongoDB 示例)

唯一索引拦截重复提交(MongoDB 示例)
// 每个业务请求带一个幂等键(客户端生成或网关下发)
db.idempotency.createIndex({ key: 1 }, { unique: true })

try {
  db.idempotency.insertOne({ key: "req-8f2c", createdAt: new Date() })
  // 首次请求:继续执行业务
} catch (e) {
  if (e.code === 11000) {
    // 重复请求:查询首次结果直接返回,或告知处理中
  } else {
    throw e
  }
}

// 清理:给幂等键设 TTL,覆盖业务允许的重试窗口即可
upsert按主键写入最新状态:重复执行结果一致(ReplacingMergeTree、ES 同 _id 覆盖同理)
版本条件带版本更新(CAS):旧版本重放不生效,防止覆盖新状态
去重表记录已处理事件 ID,与业务写入同事务提交才能保证不漏不重
幂等窗口要覆盖该接口的重试与重放周期:窗口过短,晚到的重试会重复执行;窗口过长,去重表占用增大。

易错点

  • 用"查询是否存在再插入"做去重:并发下两个请求同时查不到再同时插入,唯一索引才能挡住
  • 幂等键由服务端每次生成:同一个业务请求每次重试都换新键,等于没有幂等

数据来源与参考

  • MongoDB Manual: Unique indexes
  • Elasticsearch Guide: Index API(同 ID 覆盖语义)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌