业务接口幂等性

业务接口幂等性,第1张

总结

针对重复请求问题:使用token机制+(redis+setnx)/(redis+set)的方式
针对数据重复问题:使用代码逻辑+唯一索引/锁机制的方式
针对响应一致性问题:不要设计响应不一致的接口 todo
针对分布式并发问题:使用分布式锁

问题

接口重复请求:用户重复请求接口
接口超时重试:dubbo等框架的超时重试机制
消息重复消费:MQ等框架的消息重复消费造成多次执行消费代码

定义

维基百科:多次调用方法或者接口不会改变业务状态,可以保证重复调用的结果和单次调用的结果一致

  • 对接口的n次请求的响应是一致的,响应结果与请求次数无关
  • 考虑重复请求对数据的影响,对请求方的影响,对用户的影响
  • 接口幂等性,既要避免产生重复数据之外,还要求每次请求都返回一致的结果
方案/代码逻辑

缺点:不适用于高并发场景,高并发场景下依然会产生重复数据

增加 *** 作

说明:
对数据有唯一性要求,则不允许出现重复数据,n次请求只有首次请求增加成功,后续请求是重复请求

方式:
代码逻辑:增加前先查找,不存在则增加,存在则响应已存在

删除 *** 作

说明:
删除必须加上limit,已知delete tableName将删除整个表的数据

方式:
代码逻辑:删除前先查找,存在才删除,不存在则不进行删除 *** 作;删除必须带上limit

修改 *** 作

说明:
将reqVO赋值给PO即将请求赋值给数据库中查询得到的对象,避免直接使用reqVO更新数据库,影响了未更新的自带

方式:
代码逻辑:先查找再更新,存在则将reqVO赋值给PO再更新,不存在则不进行更新 *** 作

查询 *** 作

查询一般不存在接口幂等性问题,只要数据不变n次查询结果都是一致的

方案/唯一索引 单表+唯一索引

说明:
对数据有唯一性要求,则不允许出现重复数据,n次请求只有首次请求增加成功,后续请求是重复请求

方法:
唯一索引:表中某个字段加上唯一索引,避免对数据造成影响

缺点:

  • 无法解决假删除问题
  • 假删除字段加到组合唯一索引中也无法解决问题
  • 假删除字段没加入组合唯一索引:删除之后,无法再次插入
  • 假删除字段是时间类型加入组合唯一索引:可以一直重复插入
  • 假删除字段是bool类型加入组合唯一索引:插入、删除、插入、再删除
去重表+唯一索引

单独建立1张去重表
todo

方案/锁机制 乐观锁CAS

CAS(Compare And Swap):我期待的值和实际值(数据库中值)一致则进行下一步 *** 作

#1.首先客户端先请求服务端,先查询出当前的version版本,在update语句where条件中使用 
SELECT version FROM tableName WHERE condition;
#2.根据version版本来做sql *** 作 
UPDATE tableName SET fieldName version=(version+1) WHERE id=1 AND version=expectedVersion;
乐观锁CAS/状态机

有状态字段才能使用状态机
支付订单的状态:待付款(padding),锁定(locked),已付款(paid)等等

update `order` set status='locked' where id=1 and status='padding';
悲观锁+双重检查

步骤:加锁之前检查1次,加锁之后检查一次
行锁:

  • mysql需要使用innoDB引擎
  • id必须是主键或者唯一索引,否则会锁表
select * from tableName id=1 for update;

缺点:事务中锁住表行,其他不需要使用此事务但需要使用被锁表行的 *** 作也将等待

分布式锁

作用:分布式系统线程间的同步

将多线程并发下锁机制引入了分布式系统
使用redis或zookeeper存储分布式锁
需要同步执行的 *** 作需要先获取这个锁, *** 作执行完成后,再释放这把锁

方案/token机制 redis+setnx

作用:过滤setnx设置时间内的重复请求

步骤:

  1. 客户端请求服务端获取全局唯一token
  2. 客户端业务请求带上唯一token
  3. 服务端使用请求中的唯一tokensetnx key expireTime token,设置成功,则执行业务代码;设置失败,则返回

setnx语法

# 这个键不存在的情况下才进行设置
setnx key expireTime value

缺点:
只能保证setnx时间内没有重复请求

redis+set

作用:过滤token一致的重复请求,即过滤第2步业务请求

步骤:

  1. 客户端请求服务端获取全局唯一token,服务端将此唯一token存储在redis中
  2. 客户端业务请求带上唯一token
  3. 服务端校验请求中的唯一token和redis中的唯一token是否匹配,匹配则执行业务代码,执行成功删除此唯一token;不匹配,则返回

缺点:不能过滤组合(包含:第1步-token获取请求,第2步-业务请求)重复请求

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

原文地址: http://outofmemory.cn/langs/759115.html

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

发表评论

登录后才能评论

评论列表(0条)

保存