分布式事务(二)--常见解决方案

一、TCC方案

1、基本流程:

  • 1)Try阶段:对各个服务的资源做检测以及对资源进行锁定。
  • 2)Confirm阶段:在各个服务中执行实际的操作。
  • 3)Cancel阶段:如果任何一个服务的业务方法执行出错,执行业务逻辑的回滚操作。

2、使用场景:

除非系统的一致性要求太高,系统中核心之核心的场景,比如常见的就是资金类的场景,那可以用TCC方案了。

而且各个业务执行的时间都比较短,将这些业务操作放到一个分布式事务中。

自己手写回滚逻辑,比较恶心,业务代码很难维护。

二、本地消息表

ebay公司提出的一个思想。

1、基本流程:

1、A系统在自己本地一个事务里操作同时,插入一条数据到消息表。

2、接着A系统将这个消息发送到MQ中去。

3、B系统接收到消息之后,在一个事务里,往自己本地消息表里插入一条数据,同时执行其他的业务操作,如果这个消息已经被处理过了,那么此时这个事务会回滚,这样保证不会重复处理消息。

4、B系统执行成功之后,就会更新自己本地消息表的状态以及A系统消息表的状态。

5、如果B系统处理失败了,那么就不会更新消息表状态,那么此时A系统会定时扫描自己的消息表,如果有没处理的消息,会再次发送到MQ中去,让B再次处理。

6、这个方案保证了最终一致性,哪怕B事务失败了,但是A会不断重发消息,直到B那边成功为止。

2、总结:

问题就在于严重依赖于数据库的消息表来管理事务。
如果是高并发场景咋办呢?

三、可靠消息最终一致性方案

和上面那个方案有点像,直接基于MQ来实现事务。比如RocketMQ就支持消息事务。

1、补偿:

如果下游的事务失败,就自动不断重试直到成功。
针对重要的资金类业务进行回滚,比如B系统本地回滚后,想办法通知系统A也回滚;
或者是发送报警由人工来手工回滚。

2、总结:

这个还是比较合适的,一些互联网公司也是这么用的。
要不用RocketMQ支持的,要不基于RabbitMQ封装一套类似的逻辑出来。

3、使用场景:

适合于那那种比较耗时的操作,通过这个消息中间件做成异步调用。

四、异步处理:

很多时候都是直接发个MQ消息,然后下游消费,由中间件团队保证MQ的高可用。
下游消费的时候,如果出现异常,会自动重试,RocketMQ默认重试16次,且每次重试的时间间隔从30s到2H不断增大。
MQ如果出了问题,由中间件解决,上游要有自动重发工具,保证能快速处理异常数据。

所以,不是完全不能出现一致性问题的业务场景,没必要搞上面各种复杂方案。

五、我司内部订单系统实现方案:

1、背景:

订单系统属于电商系统最核心的模块,生成订单的时候,涉及到很多系统同步,促销、履约、wms等,引入分布式事务在2018年,或之前,那时候考虑的方案没有现在这么多。
当时能考虑的方案就两种,Tcc和Saga。

posted @ 2022-01-09 09:39  Diamond-Shine  阅读(23)  评论(0编辑  收藏  举报