其他分享
首页 > 其他分享> > 防重幂等

防重幂等

作者:互联网

前言:

在分布式系统下,服务之间相互调用,必然会存在调用失败并且进行重试的情况,在某些情况下就需要做好防重幂等。

防重和幂等是什么?

防重:避免产生重复数据

幂等:除了避免产生重复数据之外,还要求每次请求都返回一样的结果

什么情况会导致重复?

发送方发送相同的请求到服务端。

如何防重?

什么情况要做幂等?

用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。

例如:

怎么解决?

  1. 新增数据类接口,通过防重解决。
  2. 更新类接口,比如更新库存,更改状态等,通过状态,加乐观锁解决。

根据状态判断

很多业务是有状态的,比如一个订单表。有下单0、支付中1、已支付2、取消支付3等状态,

假如id=123的订单状态是0,现在要变成支付中状态。

update order set status=1 where id=123 and status=0;

第一次请求时,该订单的状态可以正常更新,sql执行结果的影响行数是1,订单状态变成了1。后面有相同的请求过来,再执行相同的sql时,由于订单状态变成了1,再用status=0作为条件,最终sql执行结果的影响行数是0,即不会真正的更新数据。但为了保证接口幂等性,接口也需要直接返回成功。

加乐观锁,在表中增加一个version字段。

在更新数据之前先查询一下数据:

select id,amount,version from user id=123;

如果数据存在,假设查到的version等于1,再使用id和version字段作为查询条件更新数据:

update user set amount=amount+100,version=version+1 where id=123 and version=1;

更新数据的同时version+1,然后判断本次update操作的影响行数,如果大于0,则说明本次更新成功,如果等于0,则说明本次更新没有让数据变更。

由于第一次请求version等于1是可以成功的,操作成功后version变成2了。这时如果并发的请求过来,再执行相同的sql:

update user set amount=amount+100,version=version+1 where id=123 and version=1;

该update操作不会真正更新数据,最终sql的执行结果影响行数是0,因为version已经变成2了,为了保证接口幂等性,接口可以直接返回成功,因为version值已经修改了,那么前面必定已经成功过一次,后面都是重复的请求。

总结

标签:请求,重复,接口,version,防重,id
来源: https://www.cnblogs.com/jiezai/p/15499774.html