接口幂等性设计

1、场景

  • 一个分布式系统中,A服务调用B服务,不论是用RPC还是restful,只要是通信,它就有可能在任何时候挂掉,所以肯定要考虑重试机制,那有重试,就处理数据的结果肯定要保持统一,最简单的,一笔订单,不能因为网络重试就扣用户两次或者多次钱吧?

2、接口幂等性是个什么?

  • 接口幂等性就是在上方描述的场景中,A服务调用B服务,一次请求或者多次请求,结果要统一,同一请求多次点击不会产生副作用。
  • 订单支付,扣款成功,但是返回结果时网络异常,此时钱已经扣了,用户再次点击按钮,此时不能进行第二次扣款,而是直接返回成功。

3、接口幂等性设计

  • 在增删改查4个操作中,查询操作在数据不变的情况下,结果是一样的,是天然的幂等操作
  • 删除操作,删一次和多次删除都是把数据删除。(注意可能返回结果不一样,删除的数据不存在,返回0,删除的数据多条,返回结果多个,在不考虑返回结果的情况下,删除操作也是具有幂等性的)
  • 更新操作,修改在大多场景下结果一样,但是如果是增量修改是需要保证幂等性的,如下例子:

把表中id为XXX的记录的A字段值设置为1,这种操作不管执行多少次都是幂等的

把表中id为XXX的记录的A字段值增加1,这种操作就不是幂等的

  • 新增操作,增加在重复提交的场景下会出现幂等性问题,如以上的支付问题
3.1 解决方案

3.1.1 唯一索引,组合唯一

  • 通过唯一索引解决新增操作可能出现的脏数据,当B服务存在唯一索引ID,在A服务生成该ID调用B服务时传过去,并发时B服务新增报错,表明数据应该已经存在了,再查询一次就可以返回结果。

3.1.2 Token令牌

  • 生成全局唯一的token,存放到redis或缓存中,A服务调用B服务,A先获取token,然后会在请求B服务时放在请求参数中,B收到请求,先校验token,执行提交逻辑,提交成功同时删除缓存中的token,生成新的token更新到缓存中 ,这样当A服务再次提交携带的token是已删除的token后,B服务校验token失败不让提交。

3.1.3 乐观锁

  • 更新操作,增量修改时可以采用乐观锁,在更新的接口中增加一个版本号,更新时先跟数据库中的数据比较版本号,看是否符号预期,符合预期就更新,不符合就返回重新查询并判断是否还需要更新,也就是CAS(Conmpare And Swap),如此来做幂等。

3.1.4 状态机

  • 这种方法适合在有状态机流转的情况下,比如订单的创建和付款,订单首先有提交(0),付款中(1),付款成功(2),付款失败(3)。
  • 当orderStatus = 1 时,其前置状态只能是0,也就是说将orderStatus由0->1 是需要幂等性的,这时候需要在执行update操作之前检测orderStatus是否已经=1,如果已经=1则直接返回true即可。
update OrdersetorderStatus=1
where
OrderId='orderid'
and
orderStatus=0
  • 但是如果此时orderStatus = 2,再进行订单状态0->1 时操作就无法成功。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值