幂等设计百科

80 阅读3分钟

一、什么是幂等(抽象定义)

幂等(Idempotent)
对同一资源的同一语义请求
执行一次和执行多次,对系统最终状态的影响完全一致

⚠️ 注意:

  • 不是“返回值一样”
  • “系统状态一样”

二、幂等问题的本质来源(所有系统通用)

根因示例
网络重试超时 / TCP 重传 / 网关重发
用户行为连点按钮 / 刷新
系统重放MQ 重投 / 定时任务补偿
并发多线程 / 多实例
分布式服务超时 + 重试
外部系统第三方回调

👉 只要“有副作用”,就一定要考虑幂等


三、幂等方案的「底层分类」(核心认知)

所有幂等方案,本质只分 4 大类

1️⃣ 唯一性约束
2️⃣ 状态机约束
3️⃣ 请求去重
4️⃣ 操作原子性

下面逐类讲 所有可用方案


四、1️⃣ 唯一性约束类(最强幂等)

1.1 数据库唯一索引(终极兜底)

适用

  • 强一致
  • 并发高
  • 插入型业务

示例

UNIQUE(order_no)
UNIQUE(biz_id + biz_type)

特点

✅ 并发 100% 安全
❌ 只能防“重复数据”

📌 结论

所有系统,只要能加唯一索引,一定要加


1.2 全局唯一业务 ID

常见

  • requestId
  • orderNo
  • tradeNo
  • messageId
UUID / 雪花 ID / 业务编码

用法

  • 请求唯一
  • 消息唯一
  • 回调唯一

五、2️⃣ 状态机约束类(最常用)

2.1 状态前置校验(逻辑幂等)

示例

if (order.status != CREATED) {
    return OK;
}
order.status = PAID;

适用

  • 审批
  • 流程
  • 状态流转

📌 这是“业务层幂等”的核心


2.2 有限状态机(FSM)

CREATED → PAYING → PAID → SHIPPED → DONE

非法状态流转直接拒绝


2.3 乐观锁(版本号 / CAS)

UPDATE table
SET status = ?, version = version + 1
WHERE id = ? AND version = ?
  • 0 行更新 = 已处理

六、3️⃣ 请求去重类(入口拦截)

3.1 Token 机制(一次性令牌)

流程

  1. 获取 token
  2. 提交携带 token
  3. token 校验 + 删除

📌 Web 表单 / 提交类接口最常用


3.2 请求指纹(Request Fingerprint)

hash(userId + params + uri)
SETNX(fingerprint)

场景

  • 防止短时间重复请求
  • 防刷

3.3 Redis SETNX(幂等锁)

SETNX(key, value, ttl)

特点

  • 快速
  • 分布式
  • 有过期时间

⚠️ 不可单独作为最终兜底


七、4️⃣ 操作原子性类(分布式必备)

4.1 数据库事务

  • 原子性
  • 回滚

📌 单体系统幂等基础


4.2 本地消息表(事务消息)

业务操作 + 消息记录 同一事务

避免重复发送


4.3 MQ 消费幂等(必须掌握)

标准做法

messageId + 唯一索引
if (processed(messageId)) return;
process();
markDone(messageId);

4.4 Exactly-Once 的真相(重要)

❌ 现实中不存在真正 Exactly-Once
At-Least-Once + 幂等 = Exactly-Once 效果


八、按「系统类型」给你完整方案矩阵

8.1 Web API

场景方案
表单提交Token + Redis
创建资源唯一业务 ID
更新状态状态机
并发乐观锁

8.2 分布式系统 / 微服务

场景方案
服务重试requestId
RPC 调用幂等接口设计
超时补偿状态校验

8.3 MQ / 事件驱动

场景方案
消费重复messageId
顺序保证分区有序
消息丢失本地消息表

8.4 第三方回调 / Webhook

场景方案
重复回调回调 ID 唯一索引
延迟回调状态判断
恶意调用签名 + 幂等

8.5 定时任务 / 补偿任务

场景方案
重跑状态判断
并发执行分布式锁
多实例乐观锁

九、幂等设计的「黄金公式」

幂等 = 唯一标识 + 状态判断 + 原子操作 + 最终兜底


十、反模式(一定要避开)

❌ 只靠 Redis 锁
❌ 只靠前端限制
❌ 没有唯一索引
❌ 把异常当幂等
❌ 以为事务 = 幂等


十一、一句话总结(架构级)

幂等不是一个功能,而是系统面对不确定性的“免疫能力”