美文网首页
分布式服务接口幂等性

分布式服务接口幂等性

作者: Spurs_27a5 | 来源:发表于2019-03-27 17:09 被阅读0次

    接口幂等性问题产生的原因:

    假如有个服务提供一个接口(服务部署在多个服务机器),接着有个接口是付款接口。用户在前端上操作的时候,一个订单不小心发起了两次支付请求,然后这两个请求分散在了这个服务部署的不同的机器上,结果一个订单扣款扣两次。

    保证幂等性的核心:

    1、对于每个请求必须有一个唯一的标识。

    2、每次处理完请求之后,必须有一个记录标识这个请求处理过了。

    3、每次接收请求需要进行判断之前是否处理过的逻辑处理。

    常见解决方案:

    1、业务表内唯一索引:

    如果要对创建销售出库单的接口保证幂等性,也就是说人家网络超时,重复调用的时候,保证一个订单只能有一个对应的销售出库单。针对销售出库单的表的订单id,创建一个唯一索引,你如果接口被重试,同一个订单创建一个销售出库单的话,一定会违反唯一索引,那么此时会报错。

    2、业务表内状态机:

    修改订单状态,比如说将订单状态修改为待发货的时候,update order set status = “待发货” where status = “待付款” and id = 1,订单的状态其实就变为了“待发货”。假如说id = 1的订单接口重复调用,又要执行一次这个操作的话就不会生效。通常会去判断一下的,当前是否处于某个状态,然后才能流转到下一个状态。 (状态为待付款的才能流转到待发货)

    3、基于版本号的更新:

    id name age version

    1 张三 20 1

    如果要调用这个接口,更新他的这个年龄,先得查一下他的版本号是多少。调用人家的接口修改他的年龄,要changeAge(1, 21, 1)。

    在接口里保证分布式接口的幂等性:

    update user set age=21, version=version+1 where id=1 and version=1

    如果这条SQL执行成功过后,如果重复调用,因为version不同,导致执行失败。

    id name age version

    1 张三 21 2

    4、基于mysql的去重表 / 基于redis的去重

    比如说接口方法为changeAge(1, 21, 1),将所有的参数拼接成一个字符串,或者是从这些入参里选择一些参数,可以唯一标识这一次请求的一些参数id和version,id和version每次请求都不一样的,应该是可以唯一的标识这一次请求。拼接的字符串:1_21_1

    如果基于mysql,单独搞一个表出来,就一个字段,建一个唯一索引,插入这个1_21_1到表里去。如果这个接口被重复调用的话,1_21_1,再次插入一个表的话,唯一索引会报一个冲突出来,这次插入就会失败。

    如果接口调用量很大,并发很高,选择使用redis,拼接一个串出来,直接set设置到redis里去,如果下一次人家请求再过来了,此时会发现这个key已经存在了,那么这个时候就不能执行了,因为已经出现重复调用了。

    相关文章

      网友评论

          本文标题:分布式服务接口幂等性

          本文链接:https://www.haomeiwen.com/subject/qmctbqtx.html