Rocket MQ分布式事务解决方式

分布式事务

一、分布式事物概念

分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上 简单的来说,就是一次大的操作由不同的小操作组成,这些小的操作那么全部成功,要么全部失败。分布式事务就是为了保证不同的数据库的数据一致性.

二、前言

目前分布式事务是还没有彻底的解决的难题,在考虑到实现方案前。需要考虑到当前项目是不是真的需要追求强的一致性。参考BASE理论,在分布式系统中,允许不同的服务节点在同步过程中存在延时,但可以经过一段时间修复,能达到数据的最终一致性。

强一致性

  • 考虑XA协议,通过二阶段提交或者三阶段提交来保证。实现起来对代码侵入性比较强

最终一致性

  • 考虑采用 TCC 模式,补偿模式,或者基于消息队列的模式。基于消息队列模式,可以采用 RocketMQ,下面我将介绍RocketMQ在分布式系统中事务中的使用。

  • 重点: Rocketmq考虑的是数据最终一致性。上游服务提交之后,下游服务最终只能成功,做不到回滚上游数据

比如有个订单服务,订单服务下面存在积分服务、商品服务、优惠券服务等。下订单的同时需要通知积分服务增加积分、商品服务减少预售库存、去优惠券服务查询订单是否有可用的优惠券。使用消息队列最终一致性可能有这么一种情况,积分服务和优惠券服务调用成功,但是对应的后台服务商品库存不足为0扣减失败情况下、如何回滚订单、积分、优惠券服务数据。消息队列下游服务最终只能成功,做不到回滚上游数据。显然可以看出使用消息队列最终数据最终一致性,是存在使用局限的。

阿里开源的Seata

不过我个人安利推荐使用下阿里开源Seata,是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了AT、TCC、SAGA 和XA事务模式

三、麒麟系统架构图

动图1

如上图所示目前操作一次麒麟系统流程是需要跨各个不同的服务进行交互。要保证这些不同的系统之间操作的数据要么全部成功要么全部失败,控制好分布式事务是很重要的。下面主要是讲解RocketMQ事务分布式事务的处理原理和方式。

四、RocketMQ事物消息

  • Apache RocketMQ在4.3.0版中已经支持分布式事务消息,这里RocketMQ采用了2PC的思想来实现了提交事务消息,同时增加一个补偿逻辑来处理二阶段超时或者失败的消息,如下图所示

动图1

RocketMQ事务消息流程概要

上图说明了事物消息的大致方案, 其中分为两个流程: 正常事物消息的发送及提交、事务消息的补偿流程。

事务消息发送及提交

  • 1、发送消息(half消息).
  • 2、服务端响应消息写入结果。
  • 3、根据发送结果执行本地事物(如果写入失败,此时half消息对业务不可见,本地逻辑不执行)
  • 4、根据本地事务状态执行Commit或者Rollback(Commit操作生成消息索引, 消息对消费者可见

补偿流程

  • 5、对没有Commit/Rollback的事务消息(pending状态的消息),定时任务从服务端发起一次“回查”。
  • 6、Producer收到回查消息,检查回查消息对应的本地事务的状态。
  • 7、根据本地事务状态,重新Commit或者Rollback。

其中、补偿阶段用于解决消息Commit或者Rollback发生超时或者失败的情况。

RocketMQ事务消息设计

一阶段:Prepared阶段(预备阶段)事务消息在一阶段对用户不可见

  • 发送half消息,将备份原消息的主题与消息消费队列,然后改变主题为RMQ_SYS_TRANS_HALF_TOPIC
  • 消费组未订阅该主题,故消费端无法消费half类型的消息,然后RocketMQ会开启一个定时任务,从Topic为RMQ_SYS_TRANS_HALF_TOPIC中拉取消息进行消费,根据生产者组获取一个服务提供者发送回查事务状态请求,根据事务状态来决定是提交或回滚消息。

二阶段:Commit和Rollback操作(确认阶段)

  • Commit : 在完成一阶段写入一条对用户不可见的消息后,二阶段如果是Commit操作,则需要让消息对用户可见;
  • Rollback : 需要撤销一阶段的消息。对于Rollback,本身一阶段的消息对用户是不可见的,其实不需要真正撤销消息。

RocketMQ 引入了Op消息 的概念,用Op消息标识事务消息已经确定状态 (Commit或者Rollback)。如果一条事务消息没有对应的Op消息,说明这个事务的状态还无法确定(可能是二阶段失败了)。引入Op消息后,事务消息无论是Commit或者Rollback都会记录一个Op操作。Commit相对于Rollback只是在写入Op消息前创建Half消息的索引(可以被消费者消费到)。

Op消息的存储和对应关系

  • RocketMQ将Op消息写入到全局一个特定的Topic中通过源码中的方法—TransactionalMessageUtil.buildOpTopic();这个Topic是一个内部的Topic(像Half消息的Topic一样),不会被用户消费。Op消息的内容为对应的Half消息的存储的Offset
  • 1
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值