关于幂等==

概念
    同意参数,多次调用接口的结果与一次调用接口的结果一致
场景
    单机:后端处理成功后向客户端响应结果,因网络原因响应失败或延时,用户不明所以,疯狂点击提交按钮。
    分布式系统:一个服务调另一个服务,被调用服务处理成功,但因为网络原因,返回给调用方,此时调用方会多次重试,此时就会存在幂等问题。
需要做幂等的接口
    update,insert。select不需要做幂等,delete暂时也没想到需要做幂等的场景。
方法
    方法太多了,根据具体业务场景可简可繁,但是必须要有一个唯一的key来做标识业务或操作。例如,insert:为避免重复insert,insert之前先查询,如果已有数据,幂等掉,否则insert,这种场景当然需要有能查询出正确记录的查询条件,如果没有,还得另想办法,或者通过唯一索引来约束。update:在作业流程中,某作业状态只能递增,不能回退,通常用1,2,3...表示某一作业状态,当更新时,先作判断,若更新值小于当前值被幂等掉,不做操作。(其实这不算真正意义上的幂等,因为一次或多次调用结果都一样的,如果update是一个递减或递增的操作,反正就是要改变其状态,就是真正意义上的幂等拉)
具体来讲一个扣款场景
    为避免订单重复支付,每次支付前先查询订单状态,如果已支付,幂等掉不做处理,若未支付,进行支付,并将订单状态置为”已支付“。常规流程这样就可以实现幂等了,但是在高并发下,会存在问题,eg. 在mySql隔离级别为“读已提交”下,同时来了两个请求,先查询订单状态,都查询到订单状态为"未支付",各自进行支付,此时就需要采取系列措施保证订单状态的正确读取了,如:(以下方式参考自其他文章)
   乐观锁
    如果只是更新已有的数据,没有必要对业务进行加锁,设计表结构时使用乐观锁,一般通过version来做乐观锁,这样既能保证执行效率,又能保证幂等。例如: UPDATE tab1 SET col1=1,version=version+1 WHERE version=#version# 不过,乐观锁存在失效的情况,就是常说的ABA问题,不过如果version版本一直是自增的就不会出现ABA的情况。(从网上找了一张图片很能说明乐观锁,引用过来,出自Mybatis对乐观锁的支持) 

   防重表
    使用订单号orderNo做为去重表的唯一索引,每次请求都根据订单号向去重表中插入一条数据。第一次请求查询订单支付状态,当然订单没有支付,进行支付操作,无论成功与否,执行完后更新订单状态为成功或失败,删除去重表中的数据。后续的订单因为表中唯一索引而插入失败,则返回操作失败,直到第一次的请求完成(成功或失败)。可以看出防重表作用是加锁的功能。

   分布式锁
    这里使用的防重表可以使用分布式锁代替,比如Redis。订单发起支付请求,支付系统会去Redis缓存中查询是否存在该订单号的Key,如果不存在,则向Redis增加Key为订单号。查询订单支付已经支付,如果没有则进行支付,支付完成后删除该订单号的Key。通过Redis做到了分布式锁,只有这次订单订单支付请求完成,下次请求才能进来。相比去重表,将放并发做到了缓存中,较为高效。思路相同,同一时间只能完成一次支付请求。
   防重表和分布式锁,实则都是为了保证用一时刻只有一个服务在处理请求 ,只是实现的方式不一样。(防重表和Redis更像是分布式锁实现的两种方式)

   token令牌
    这种方式分成两个阶段:申请token阶段和支付阶段。 第一阶段,在进入到提交订单页面之前,需要订单系统根据用户信息向支付系统发起一次申请token的请求,支付系统将token保存到Redis缓存中,为第二阶段支付使用。 第二阶段,订单系统拿着申请到的token发起支付请求,支付系统会检查Redis中是否存在该token,如果存在,表示第一次发起支付请求,删除缓存中token后开始支付逻辑处理;如果缓存中不存在,表示非法请求。 实际上这里的token是一个信物,支付系统根据token确认,你是你妈的孩子。不足是需要系统间交互两次,流程较上述方法复杂。

详细可参考:https://www.cnblogs.com/javalyy/p/8882144.html 

顺便提一下后端防止请求重复提交的方法:跳转到提交页面时,先申请一个token,并将token存入Redis (分布式环境下,单机环境直接存到一个全局变量中即可),将token带到跳转页面,提交请求时带token提交,后台接收请求后将该token从Redis中删除,表示已经接受了本次请求,如果此时又有一个带相同token的请求过来,发现从Redis中未获取到该token,说明此token所对应的请求已经被处理过了,此次不再处理,这是后端放置重复提交的方法,当然,前端手段的话,一次请求提交后就禁用提交按钮,避免用户无意识的重复提交,但是如果若故意重复提交,就没法啦,后台需要做处理。

消息重复推送的幂等==

写得很好:https://825635381.iteye.com/blog/2276077
 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值