文章目录
- 什么是幂等(Idempotence)
- 幂等操作
- 非幂等操作
- 为什么分布式系统必须要幂等
- HTTP 方法中的幂等
- GET
- PUT
- DELETE
- POST
- 幂等键
- 数据库实现思路
- 幂等键还要校验请求内容
- 前端类比
- 幂等处理的常见方案
- 示例 1:通过请求唯一 ID 做幂等(Redis 实现)
- 示例 2:MySQL 唯一约束防止重复插入
- 示例 3:接口幂等 token(电商常见)
- 总结
什么是幂等(Idempotence)
简单说:
一次请求和多次请求的结果是一样的,不会因为重复请求造成数据异常或重复处理。换句话说:同一个操作执行一次和重复执行多次,最终产生的业务状态相同。
数学上可以写成:
f(f(x)) = f(x)幂等操作
POST /order/pay?id=12345无论你请求一次,还是网络原因请求了 3 次,只会支付一次订单,不会重复扣钱或生成多个支付记录。
非幂等操作
UPDATEaccountSETbalance=balance-100WHEREid=1;如果这个请求执行了两次,就会多扣 100 块!
为什么分布式系统必须要幂等
在 WHAT - 事务?transaction?单个数据库事务和分布式事务 中我们介绍分布式系统中的事务(更复杂)时提及过幂等处理。
“幂等处理能力”是做分布式系统时非常关键的一个概念,尤其是在涉及重试、失败补偿、消息队列等场景中,系统必须要有能力抵抗重复请求带来的副作用。
因为在以下场景中,请求可能会被多次发送:
- 网络超时重试(调用方/中间件自动重试)
- MQ 消息重复投递
- 事务补偿机制触发多次补偿逻辑
- 客户端点击多次、刷新操作
如果处理逻辑不具备幂等性,就可能导致:
- 订单重复扣款
- 重复发货
- 积分多次增加/减少
- 资源状态错乱(库存被扣光)
所以幂等真正解决的是:
请求结果不确定时,客户端可以安全重试。
HTTP 方法中的幂等
偶尔在面试中会被问:哪些 http 方法是幂等的,哪些是非幂等的?
| 方法 | 通常是否幂等 | 示例 |
|---|---|---|
| GET | 是 | 查询文章 |
| PUT | 是 | 把文章完整设置为指定内容 |
| DELETE | 是 | 删除指定文章 |
| POST | 通常不是 | 创建订单、发起支付 |
| PATCH | 不一定 | 取决于修改方式 |
GET
GET /posts/1重复查询不会改变文章状态,所以幂等。
PUT
PUT /users/1 Content-Type: applicat