接口的幂等性设计

接口的幂等性设计,第1张

定义

接口一次请求和多次请求的结果一致。

单机和分布式下的区别

以往在单机环境下,即使接口返回因为网络问题而丢失,用户仍然可以通过查询页面来确认有无 *** 作成功,但是在分布式环境中存在调用关系,调用关系除了成功和失败还新增一种状态超时,这个时候有必要发起重试机制,而在重试的过程中,幂等性的问题就会被放大。

为什么需要幂等

例如转账业务,服务A请求服务B时返回结果超时,这个时候发起重试再次请求,应该是转账一笔而不是两笔。

创建订单需要减库存,如果减库存的接口超时了,重复调用应该保证不会多减一次库存。

3. 接口超时了,到底如何处理

服务B转账接口支持幂等,服务A重新发起请求即可。
服务B转账接口不支持幂等,服务A先调用服务B的查询接口,如果查询失败则发起转账流程,如果查询成功则代表已经转账成功,继续成功流程即可。

数据库幂等

select语句是天然幂等的,无论查询多少次都不会有问题。
delete语句可以利用唯一索引的值来进行删除或逻辑删,多次请求效果一致。
insert语句需要保证幂等性。
update语句需要保证幂等性。
其中update by id是幂等的,只修改一条记录,无论多少次都是一样的。
使用乐观锁的时候应该注意以下方式是错误的,注意在where中比较verion字段是否发生变化。

update order set version = #{version} +1,status='1' where order_id='123456' 
乐观锁

数据库新增version字段,version设置为自增每次都进行+1,为了避免ABA问题,当更新时查询version字段。

select order_id,version from order where order_id='123456'update order set version = #{version} +1,status='1' where order_id='123456' and version = #{version}
悲观锁

select … for update

Mysql中的悲观锁会有性能问题,一般不会采用。

方案一 insert唯一索引

将不会重复字段值的字段设置为唯一索引 UNIQUE 类型,直接执行插入,表中没有记录则插入成功,表中有记录则会提示主键异常,捕获后返回成功。

方案二 先select后insert唯一索引

在insert的基础上,多增加一层防重处理,新增记录时,先去查询库中有无记录,如果有则直接返回,如果没有在执行插入。

方案三 状态字段幂等

对于很多业务是有一个业务流转状态的,每个状态都有前置状态和后置状态,以及最后的结束状态。例如流程的待审批,待审批、通过、拒绝。订单的待提交,待支付,已支付,已取消。

以订单为例,已支付的状态的前置状态只能是待支付,而取消状态的前置状态只能是待支付,通过这种状态机的流转我们就可以控制请求的幂等。

在枚举中设计前置状态字段,根据变更状态和前置状态可以控制请求的幂等。

方案四 防重表

唯一索引:

需求是博客点赞问题,要想防止一个人重复点赞,可以设计一张表,将博客id与用户id绑定建立唯一索引,每当用户点赞时就往表中写入一条数据,这样重复点赞的数据就无法写入。

方案五 Token机制

在某些业务,需要前端先去获取Token值,将Token放在请求头中,执行创建订单时发送Token,后端将Token写入Redis中并设置一个过期时间,接口获取请求头中的Token并跟Redis中的值进行比较,如果存在则代表第一次请求,redis中删除Token,后续请求比较失败直接返回。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/734604.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-04-27
下一篇2022-04-27

发表评论

登录后才能评论

评论列表(0条)

    保存