【设计】接口幂等性设计
1. 幂等性定义
接口幂等性: 无论调用次数多少,对系统状态的影响与单次调用相同。
比如用户支付接口因网络延迟重复提交了三次。
导致原因:
- 用户不可靠(手抖多点)
- 网络不可靠(超时重传)
- 系统不可靠(服务重试)
2. 解决方案?
-
使用token机制防抖
token存在Redis中,删除token执行任务,否则就直接返回重复请求。 -
唯一索引
创建类操作。 -
乐观锁(更新操作首选)
通过版本号机制控制数据更新。 -
分布式锁(高并发场景)
-
状态机(业务流程控制)
-
请求序列号(复杂业务流)
金融交易系统中常用,使用业务序列号,该序列号被处理,则返回缓存中的数据,否则直接处理相应的业务。
3. 案例
3.1 电商秒杀
10万QPS下如何保证库存扣减的幂等性?
- 预扣库存:Redis缓存库存数
- 请求序列号:用户Id+秒杀场次生成唯一Id
- 异步落库:MQ消费报保证最终一致性
public Result seckill(String userId, String activityId) {String bizId = userId + ":" + activityId;if(redis.setnx(bizId, "1") == 0 ) {return Result.error("重复请求");}redis.expire(bizId, 30);Long stock = redis.decr("stock:" + activityId);if(stock<0) {return Result.error("已售罄");}mq.send(new OrderMessage(userId, activityId));return Result.success("排队中");
}
3.2 银行转账系统
- 全局交易流水号(支付系统生成)
- 事务表唯一索引
- 账号余额变更使用CAS操作
update account
set balance = balance-100,version=version+1
where user_id = 123
and version = 5;
参考:草捏子