**幂等(Idempotent)**是分布式系统和接口设计中的一个重要概念,指的是:一次请求和多次请求的执行效果是一样的,副作用不会叠加。
✅ 一、通俗理解
幂等操作就是:无论你执行一次,还是执行一百次,系统的状态都是一样的。
比如:
-
你给某条记录加一次锁,再加 99 次锁,状态仍是“已加锁”;
-
给用户账户设置密码为“123456”,设置几次都一样;
-
删除一条记录,如果已删除,再删也不会出错。
✅ 二、幂等在系统中的关键价值
场景 | 为什么需要幂等 |
---|---|
网络重试 | 请求超时/失败后客户端或中间件重试,避免数据重复操作 |
消息重复消费 | 消息队列保证 至少一次投递,消费方必须能处理重复消息 |
分布式事务 | 某些补偿逻辑可能会被执行多次,必须设计为幂等操作 |
接口幂等性 | 外部 API 调用必须避免重复下单、重复扣款等严重后果 |
✅ 三、常见业务场景的幂等处理策略
1️⃣ 数据库约束控制幂等
使用唯一索引或唯一主键,防止重复插入。
INSERT INTO orders (order_id, user_id) VALUES (?, ?)
-- 若 order_id 是唯一键,重复执行会失败,不会重复下单
2️⃣ 利用业务唯一标识(幂等键)
每次请求携带一个 唯一幂等标识
(如:requestId
, orderId
, txId
):
-
后端记录该标识,第一次处理后保存结果;
-
之后再来相同标识的请求,直接返回上次结果,不重复执行核心逻辑。
if (idempotentStore.contains(requestId)) {
return idempotentStore.get(requestId); // 直接返回
} else {
Result res = doBusiness();
idempotentStore.save(requestId, res);
return res;
}
3️⃣ 利用 Redis 实现幂等控制
// SETNX:只设置一次幂等键
boolean success = redis.setIfAbsent("idempotent:tx123", "1", 10, TimeUnit.MINUTES);
if (!success) {
throw new RepeatSubmitException("重复提交");
}
4️⃣ 逻辑幂等处理(查状态后再执行)
如:支付接口先判断订单状态是否为“未支付”,再执行支付逻辑:
if (order.getStatus() == UNPAID) {
order.setStatus(PAID);
pay();
}
✅ 四、常见不幂等操作举例(危险)
操作 | 幂等性 | 风险说明 |
---|---|---|
转账扣款 | ❌ | 多次扣款,资金损失 |
新建订单 | ❌ | 重复下单,数据污染 |
积分累计 | ❌ | 重复加分,积分异常 |
✅ 五、接口设计上的幂等建议
-
GET 接口必须幂等(天然幂等)
-
POST 接口也要设计幂等机制(通过幂等标识、token、状态判断等)
-
可考虑引入 防重复提交 token、幂等服务中间件 来简化设计
✅ 六、总结一句话
幂等是保证“重复操作不会造成系统状态变化”的一种设计原则,是高可用系统的核心基础能力。
是否需要我提供一个基于 Spring Boot + Redis 的接口幂等控制完整示例?或者说明如何设计 MQ 消费幂等性逻辑?