分布式事务

原创
07/11 17:35
阅读数 47

分布式事务处理机制共有四种:

  1. 两阶段提交
  2. TCC事务(事务补偿)
  3. 本地消息表(异步确保),
  4. MQ事务消息。

两阶段提交:

与数据库XA事务一样,两阶段提交使用XA协议。

两阶段提交这种方案属于牺牲了一部分可用性来换取的一致性。

优点:尽量保证了数据的强一致,适合对数据强一致要求很高的关键领域。

缺点:实现复杂,牺牲了可用性,对性能影响较大,不适合高并发高性能场景,如分布式系统跨接口调用。

TCC事务:

TCC其实就是采用的补偿机制,其核心思想是:针对每个操作,都要注册一个与其对应的确认和补偿操作。分为三个阶段:

  1. Try阶段主要是对业务系统做检测和资源预留。
  2. Confirm阶段主要是对业务系统做确认提交,Try阶段执行成功并开始执行Confirm阶段时,默认Confirm阶段是不会出错的。即:只要Try成功,Confirm一定成功。
  3. Cancel阶段主要是在业务执行错误,需要回滚的状态下,执行的业务取消,预留资源释放。

优点:跟2阶段提交比起来,实现及流程相对简单了些,但数据的一致性也要比2阶段提交要差一些。

缺点:在2,3步中都可能失败。TCC是一种应用层的补偿方式,需要程序员在实现时写很多补偿的代码,一些场景中,一些业务流程用TCC不太好定义及处理。

本地消息表:

使用最多的,核心思想是将分布式事务拆分成本地事务进行处理,来源于ebay。

基本思路就是:

消息生产方,需要额外建一个消息表,并记录消息发送状态。消息表和业务数据要在一个事务里提交,也就是说他们要在一个数据库里面。然后会经由MQ发送到消息的消费方。如果消息发送失败,会进行重试发送。

消息消费方,需要处理这个消息,并完成这个的业务逻辑。如果此时本地事务处理成功,表明已经处理成功了,如果处理失败,那么就会重试执行。如果是业务上面的失败,可以给生产方发送一个业务补偿消息,通知生产方进行回滚等操作。

生产方和消费方定时扫描本地消息表,把还没处理完成的消息或者失败的消息在发送一遍。

这种方案遵循最终一致性。

优点:一种非常经典的实现, 避免的分布式事务,实现了最终一致性。

缺点:消息表会耦合到业务系统中,如果没有封装好的解决方案,会有很多杂活需要处理。

MQ事务消息:

有一些第三方的MQ是支持事务消息的,比如RocketMQ,他们支持事务消息的方式也是类似于采用的二阶段提交,但一些主流的MQ都是不支持事务消息的,如RabbitMQ和Kafka都不支持。

以阿里的RocketMQ为例:

第一阶段Prepared消息,会拿到消息的地址。

第二阶段执行本地事务,第三阶段通过第一阶段拿到的地址去访问消息,并修改状态。

也就是说在业务方法内部要想消息队列提交两次请求,一次发送消息和一次确认消息。如果确认消息发送失败了,RocketMQ会定期扫描消息集群中的事务消息,这是发现了Prepared消息,它会像消息发送者确认,所以生产方需要实现一个check接口,RocketMQ会根据发送端设置的策略来决定是回滚还是继续发送确认消息。这样就保证了消息发送与本地事务同时成功或同时失败。

优点:实现了最终一致性,不需要依赖本地数据库事务。

缺点:实现难度大,主流MQ不支持,RocketMQ事务消息部分代码未开源。

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
在线直播报名
返回顶部
顶部