[分布式]接口幂等性
接口幂等性的设计
资料
一口气说出四种幂等性解决方案,面试官露出了姨母笑~ - 掘金
imooc\Java架构师体系课:跟随千万级项目从0到100全过程高效成长\第17周.分布式接口幂等性,分布式限流
概念、原理
问题提出:
表单如何防止重复提交? 比如页面卡了, 连续点了几次按钮;
微服务的接口, 重试多次时怎么处理?
处理:
前端: 避免提交多次
后端: 接口幂等设计
什么是幂等: 执行一次和执行多次效果一致;
什么场景需要幂等: 表单提交, 接口重试, 前端操作抖动;
业务场景: 提交订单、支付等, 根据业务确定是否需要幂等;
幂等性的核心思想:通过唯一的业务单号保证幂等;
非并发情况下,查询业务单号有没有操作过,没有则执行操作; 并发的情况下,整个操作过程加锁
幂等改造流程:
- 接口是否本身就是幂等的?
- 是否需要改造为幂等的?
- 是否存在唯一业务单号? (如果不存在使用token机制)
实现幂等的方法:
加唯一索引, 避免重复插入;
update使用乐观锁;
分布式锁不释放, 等待超时释放;
token机制;
token机制:
- 进入表单页面时, 后台统一生成token(比如uuid), 存到redis, 返回给前端
- 前端提交表单时, 把token一起提交给后端
- 后端判断redis中是否存在token, 如果存在就删除token, 再执行任务, 如果不存在直接返回或抛出异常; (注意: 在并发情况下, redis查找、删除需要保证原子性,可以使用分布式锁或者使用Lua脚本)
数据库增删改查等五种情况分析
select: 天然幂等
delete:
如果根据唯一单号(主键)删除, 多次操作没有影响, 支持幂等, 不需要处理;
如果不是根据唯一单号删除, 根据业务确定是否需要幂等, 如果需要用token机制;
比如: 根据审核状态删除商品信息;
update:
某些情况执行多次结果一致, 不需要处理, 比如:
update table_x set a = 100 where id = 'xxx'
某些情况需要处理:
update table_x set a = a + 1 where id = 'xxx'
解决: 使用乐观锁, 加上版本号作为更新条件:
update table_x set version=version + 1,a = a + 1 where id='xxx' and version = ${version}
insert:
找唯一单号(比如秒杀商品id+用户id), 找不到用token, 然后按照token机制处理;
混合操作, 一个接口包含多种操作; 同insert的情况;