幂等系统设计

2020-10-12  本文已影响0人  定金喜

1.系统为什么需要幂等

2. 解决方案

  1. 接口的流量控制,通过分布式锁来对接口进行流量限制,对于一些可能存在幂等问题的接口,可以限制每个用户每几秒才能调用一次;
  2. 业务控制,例如创建用户的功能,可以在用户表中设置用户名字段为唯一索引,插入用户记录前先查询一下用户是否存在,存在则返回失败提示;电商中在购物车下单时,为了防止出现创建多个订单的情况,可以在订单表维护一个购物车标识的字段,下单时先校验该字段是否在订单表存在,存在则返回失败等等
  3. 注意状态机变化,很多业务会存在状态的流转,例如订单会存在未支付,支付中,支付成功,支付失败,退款等等状态,而且进行状态流转时,必须判断前置状态,否则不能更新,根据更新记录数量来判断是否更新失败,从而来做后续的业务操作 update order set status='支付成功' where status='支付中'

第一种:2PC 理论可以参照文章 https://blog.csdn.net/w372426096/article/details/80449695
还是以银行转账为例,我们引入一个协调者,首先,协调者对A和B账户进行询问并且两个账户分别进行操作,但是不提交事务,我的理解是A账户增加一条冻结记录,并将可用余额扣减,冻结余额增加,如果执行成功返回YES,否则返回NO;B账户也是增加一条冻结流水,可用余额暂时不会增加,如果执行成功返回YES,否则返回NO;第二个阶段,协调者根据两个返回的值来判断下一步操作:如果都返回YES,则发送通知,让A的冻结余额扣除;B的可用余额增加;如果收到NO,则进行回滚,A的可用余额加回来,B的冻结记录删除。

第二种:3PC
在2PC的基础上,将第一个阶段一分为二,canCommit和preCommit,具体理论可以百度,3PC和2PC最大的区别是增加了超时自动提交的机制,当参与者处于preCommit或者commit时,如果由于网络或者协调者宕机等问题,导致参与者阻塞超时时,参与者也会自动提交,避免了2PC由于网络等问题导致的参与者长时间阻塞问题,分析了下原因,因为系统认为处于preCommit状态的参与者,极大概率是可以进行commit的,但是不能最终解决这种问题,因为
处于preCommit状态不一定最终就可以进行commit,可能某个参与者在preCommit执行失败,可能会导致最终的数据不一致性。

第三种:TCC 补偿型
还是以A银行账户向B银行账户转账为例,调用转账接口之前,先冻结A金额,并且插入转账记录,一般银行接口会提供幂等字段做查询用,然后调用银行转账接口;使用定时任务或者一部任务等拿这个幂等的字段去B银行查询,如果成功,则A金额解冻。TCC会有很多补偿性代码,当业务较复杂时,补偿性代码会很多。还有用MQ实现分布式事务的,RocketMQ支持分布式事务,它能保证A银行的插入转账记录和发送消息给B银行加钱这两个逻辑肯定会同时成功或者失败,但是我觉得最后可能还是会结合补偿代码进行结合来保障最终的一致性。

上一篇 下一篇

猜你喜欢

热点阅读