里程碑 | Apache RocketMQ 正式开源分布式事务消息

简介: 近日,Apache RocketMQ 社区正式发布4.3版本。此次发布不仅包括提升性能,减少内存使用等原有特性增强,还修复了部分社区提出的若干问题,更重要的是该版本**开源了社区最为关心的分布式事务消息**,而且实现了对外部组件的零依赖。接下来,本文将详细探秘RocketMQ事务消息的设计原理以及实现机制。

近日,Apache RocketMQ 社区正式发布4.3版本。此次发布不仅包括提升性能,减少内存使用等原有特性增强,还修复了部分社区提出的若干问题,更重要的是该版本开源了社区最为关心的分布式事务消息,而且实现了对外部组件的零依赖。接下来,本文将详细探秘RocketMQ事务消息的设计原理以及实现机制。

_Apache_RocketMQ_

一、需求缘起

在微服务架构中,随着服务的逐步拆分,数据库私有已经成为共识,这也导致所面临的分布式事务问题成为微服务落地过程中一个非常难以逾越的障碍,但是目前尚没有一个完整通用的解决方案。

其实不仅仅是在微服务架构中,随着用户访问量的逐渐上涨,数据库甚至是服务的分片、分区、水平拆分、垂直拆分已经逐渐成为较为常用的提升瓶颈的解决方案,因此越来越多的原子操作变成了跨库甚至是跨服务的事务操作。最终结果是在对高性能、高扩展性,高可用性的追求的道路上,我们开始逐渐放松对一致性的追求,但是在很多场景下,尤其是账务,电商等业务中,不可避免的存在着一致性问题,使得我们不得不去探寻一种机制,用以在分布式环境中保证事务的一致性。

二、理论基石

微服务使得单体架构扩展为分布式架构,在扩展的过程中,逐渐丧失了单体架构中数据源单一,可以直接依赖于数据库进行事务操作的能力,而关系型数据库中,提供了强大的事务处理能力,可以满足ACID(Atomicity,Consistency,Isolation,Durability)的特性,这种特性保证了数据操作的强一致性,这也是分布式环境中弱一致性以及最终一致性能够得以实现的基础。

数据一致性分为三个种类型:强一致性,弱一致性以及最终一致性,正如上文所述,数据库实现的就是强一致性,能够保证在写入一份新的数据库,立即使其可见。最终一致性是弱一致性的强化版,系统保证在没有后续更新的前提下,系统最终返回上一次更新操作的值。在没有故障发生的前提下,不一致窗口的时间主要受通信延迟,系统负载和复制副本的个数影响。

然而,微服务作为分布式系统,同样受CAP[1] 原理的制约,在CAP理论中,

C:Consistency

A:Availability

P:Partition tolerance

三者不可同时满足,而服务化中,更多的是提升A以及P,在这个过程中不可避免的会降低对C的要求,因此,BASE理论随之而来。

BASE[2] 理论来源于ebay在2008年ACM中发表的论文,BASE理论的基本原则有三个:Basically Available,Soft state,Eventually consistent,主要目的是为了提升分布式系统的可伸缩性,论文同样阐述了如何对业务进行调整以及折中的手段,BASE理论的提出为分布式事务的发展指出了一个方向。

在最终一致性的实现过程中,最基本的操作就是保证事务参与者的幂等性,所谓的幂等性,就是业务方能够使用相关的手段,保证单个事务多次提交依然能够保证达到同样的目的。

三、当前解决方案

1、2PC/3PC

谈到分布式事务,首先要说的就是2PC(two phase commit)方案,如下图所示[3]:
_2018_08_09_5_45_31

2PC把事务的执行分为两个阶段,第一个阶段即prepare阶段,这个阶段实际上就是投票阶段,协调者向参与者确认是否可以共同提交,再得到全部参与者的所有回答后,协调者向所有的参与者发布共同提交或者共同回滚的指令,用以保证事务达到一致性。

但是分布式系统中的所有通信均存在着三种状态:成功,失败,超时。其中,超时状态的存在是我们在设计分布式系统时所面对的永远的痛,2PC同样存在问题,尤其是在发送完可以提交的指令后,参与者在没有收到提交或者回滚的指令时,面对已经上锁的资源,面对已经写出去的undo或者redo日志,参与者会一时陷入手足无措的状态,为了解决这个问题,3PC应运而生,如下图所示[4]:

_2018_08_09_5_46_18

3PC在commit之前增加了preCommit的过程,使得在参与者在收不到确认时,依然可以从容commit或者rollback,避免资源锁定太久导致浪费。但是3PC同样存在着很多问题。实现起来非常复杂,因为很难通过多次询问来解决系统间分歧问题,尤其是存在超时状态互不信任的分布式网络中,这也就是著名的拜占庭将军问题[5]。

总结一下,2PC是几乎所有分布式事务算法的基础,后续的分布式事务算法几乎都由此改进而来,其优缺点非常明显:

» 优点:在于已经有较为成熟的实现方案,比如XA。
» 缺点:XA是一个阻塞协议。服务在投票后需要等待协调器的决定,此时服务会阻塞并锁定资源。由于其阻塞机制和最差时间复杂度高, 因此,这种设计不能适应随着事务涉及的服务数量增加而扩展的需要,很难用于并发较高以及子事务声明周期较长(long-running transactions)的分布式服务中。

2、SAGA

SAGA算法[6] 于1987年提出,是一种异步的分布式事务解决方案,其理论基础在于,其假设所有事件按照顺序推进,总能达到系统的最终一致性,因此saga需要服务分别定义提交接口以及补偿接口,当某个事务分支失败时,调用其它的分支的补偿接口来进行回滚,saga的具体实现分为两种:Choreography以及Orchestration:

(1) Choreography:如下图所示:
_2018_08_09_5_48_11

这种模式下不存在协调器的概念,每个节点均对自己的上下游负责,在监听处理上游节点事件的同时,对下游节点发布事件。

(2)Orchestration:存在中心节点的模式,如下图所示:

_2018_08_09_5_48_20

该中心节点,即协调器知道整个事务的分布状态,相比于无中心节点方式,该方式有着许多优点:

  • 能够避免事务之间的循环依赖关系;
  • 参与者只需要执行命令/回复(其实回复消息也是一种事件消息),降低参与者的复杂性;
  • 开发测试门槛低;
  • 在添加新步骤时,事务复杂性保持线性,回滚更容易管理。因此大多数saga模型实现均采用了这种思路。

总结一下:SAGA模型的优点在于其降低了事务粒度,使得事务扩展更加容易,同时采用了异步化方式提升性能。但是其缺点在于很多时候很难定义补偿接口,回滚代价高,而且由于SAGA在执行过程中采用了先提交后补偿的思路进行操作,所以单个子事务在并发提交时的隔离性很难保证。

3、TCC

_2018_08_09_5_50_52

TCC(Try-Confirm-Concel)模型[7] 同样是一种补偿性事务,主要分为Try:检查、保留资源,Confirm:执行事务,Concel:释放资源三个阶段,如下图所示:

其中,活动管理器记录了全局事务的推进状态以及各子事务的执行状态,负责推进各个子事务共同进行提交或者回滚。同时负责在子事务处理超时后不停重试,重试不成功后转手工处理,用以保证事务的最终一致性。

总结一下,相比于SAGA模型,其优点在于尝试阶段仅仅只是对业务系统做检测,并保留业务资源,并没有真正提交,所以后续SAGA需要针对提交的事务做补偿,而TCC则仅仅需要释放保留资源,降低了补偿成本;并且,由于在Try阶段对资源进行了保留锁定,所以相比于SAGA模式,TCC模式拥有更高的隔离性。

缺点:相比于SAGA模式,TCC模式多增加了一个状态,导致在业务开发过程中,复杂度上升,而且协调器与子事务的通信过程增加,状态轮转处理也更为复杂。

四、事物消息**

以购物场景为例,张三购买物品,账户扣款100元的同时,需要保证在下游的会员服务中给该账户增加100积分。由于数据库私有,所以导致在实际的操作过程中会出现很多问题,比如先发送消息,可能会因为扣款失败导致账户积分无故增加,如果先执行扣款,则有可能因服务宕机,导致积分不能增加,无论是先发消息还是先执行本地事务,都有可能导致出现数据不一致的结果。
_2018_08_09_5_51_02

事务消息的本质就是为了解决此类问题,解决本地事务执行与消息发送的原子性问题。目前,事务消息在多种分布式消息中间件种均有实现,但是其实现方式思路却各有不同。

1、传统事务消息实现

传统事务消息实现,一种思路是依赖于AMQP协议用来确保消息发送成功,AMQP模式下需要在发送在发送事务消息时进行两阶段提交,首先进行tx_select开启事务,然后再进行消息发送,最后进行消息的commit或者是rollback。这个过程可以保证在消息发送成功的同时本地事务也一定成功执行,但事务粒度不好控制,而且会导致性能急剧下降,同时依然无法解决本地事务执行与消息发送的原子性问题。

还有另外一种思路,就是通过保证多条消息的同时可见性来保证事务一致性。但是此类消息事务实现机制更多的是用到consume-transform-produce场景中,其本质还是用来保证消息自身事务,并没有把外部事务包含进来。

2、RocketMQ事务消息

RocketMQ事务消息设计则主要是为了解决Producer端的消息发送与本地事务执行的原子性问题,RocketMQ的设计中broker与producer端的双向通信能力,使得broker天生可以作为一个事务协调者存在;而RocketMQ本身提供的存储机制,则为事务消息提供了持久化能力;RocketMQ的高可用机制以及可靠消息设计,则为事务消息在系统在发生异常时,依然能够保证事务的最终一致性达成。

2.1 RocketMQ 事务消息设计

事务消息作为一种异步确保型事务, 将两个事务分支通过MQ进行异步解耦,RocketMQ事务消息的设计流程同样借鉴了两阶段提交理论,整体交互流程如下图所示:
_2018_08_09_5_51_13

事务发起方首先发送prepare消息到MQ。

在发送prepare消息成功后执行本地事务。

根据本地事务执行结果返回commit或者是rollback。

如果消息是rollback,MQ将删除该prepare消息不进行下发,如果是commit消息,MQ将会把这个消息发送给consumer端。

如果执行本地事务过程中,执行端挂掉,或者超时,MQ将会不停的询问其同组的其它producer来获取状态。

Consumer端的消费成功机制有MQ保证。

2.2 RocketMQ事务消息实现

RocketMQ事务消息在实现上充分利用了RocketMQ本身机制,在实现零依赖的基础上,同样实现了高性能、可扩展、全异步等一系列特性。

在具体实现上,RocketMQ通过使用Half Topic 以及Operation Topic 两个内部队列来存储事务消息推进状态,如下图所示:

其中,Half Topic对应队列中存放着prepare消息,Operation Topic对应的队列则存放了prepare message对应的commit/rollback消息,消息体中则是prepare message对应的offset,服务端通过比对两个队列的差值来找到尚未提交的超时事务,进行回查。

在具体实现上,事务消息作为普通消息的一个应用场景,在实现过程中进行了分层抽象,从而避免了对RocketMQ原有存储机制的修改,如下图所示:
_2018_08_09_5_51_25

从用户侧来说,用户需要分别实现本地事务执行以及本地事务回查方法,因此只需关注本地事务的执行状态即可;而在service层,则对事务消息的两阶段提交进行了抽象,同时针对超时事务实现了回查逻辑,通过不断扫描当前事务推进状态,来不断反向请求Producer端获取超时事务的执行状态,在避免事务挂起的同时,也避免了Producer端的单点故障。而在存储层,RocketMQ通过Bridge封装了与底层队列存储的相关操作,用以操作两个对应的内部队列,用户也可以依赖其它他存储介质实现自己的service,RocketMQ会通过ServiceProvider加载进来。

从上述事务消息设计中可以看到,RocketMQ事务消息较好的解决了事务的最终一致性问题,事务发起方仅需要关注本地事务执行以及实现回查接口给出事务状态判定等实现,而且在上游事务峰值高时,可以通过消息队列,避免对下游服务产生过大压力。

事务消息不仅适用于上游事务对下游事务无依赖的场景,还可以与一些传统分布式事务架构相结合,而MQ的服务端作为天生的具有高可用能力的协调者,使得我们未来可以基于RocketMQ提供一站式轻量级分布式事务解决方案,用以满足各种场景下的分布式事务需求。

作者介绍:

冯嘉,阿里巴巴 RocketMQ布道师,具有丰富的分布式软件架构、高并发网站设计、性能调优经验,拥有国内外多项分布式、推荐领域的专利授权。目前专注于大规模分布式系统、分布式消息引擎、流计算领域,关注 Hbase/Hadoop/Spark/Flink等大数据技术栈。

杜恒,阿里巴巴技术专家,Apache RocketMQ内核控,拥有多年分布式系统研发经验,对Microservice, Messaging,Storage等领域有深刻理解,拥有多年金融领域开发设计经验。目前专注RocketMQ内核优化以及Messaging生态建设。

五、参考文献

[1] https://en.wikipedia.org/wiki/Cap

[2] https://dl.acm.org/citation.cfm?id=1394128

[3] https://en.wikipedia.org/wiki/Two-phase_commit_protocol

[4] https://en.wikipedia.org/wiki/Three-phase_commit_protocol

[6] https://www.cs.cornell.edu/andru/cs711/2002fa/reading/sagas.pdf

[7] https://www.cloud.alipay.com/docs/2/69656

相关实践学习
5分钟轻松打造应对流量洪峰的稳定商城交易系统
本实验通过SAE极速部署一个微服务电商商城,同时结合RocketMQ异步解耦、削峰填谷的能力,带大家体验面对流量洪峰仍旧稳定可靠的商城交易系统!
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
相关文章
|
12月前
|
消息中间件 人工智能 Apache
Apache RocketMQ 中文社区全新升级!
RocketMQ 中文社区升级发布只是起点,我们将持续优化体验细节,推出更多功能和服务,更重要的是提供更多全面、深度、高质量的内容。
838 67
|
6月前
|
消息中间件 存储 Apache
恭喜 Apache RocketMQ、Apache Seata 荣获 2024 开源创新榜单“年度开源项目”
近日,以“新纪天工、开物焕彩——致敬开源的力量”为活动主题的“重大科技成就发布会(首场)”在国家科技传播中心成功举办,并隆重揭晓了 2024 开源创新榜单,旨在致敬中国开源力量,传播推广开源科技成就,营造中国开源创新生态。2024 年开源创新榜单由中国科协科学技术传播中心、中国计算机学会、中国通信学会、中国科学院软件研究所共同主办,中国开发者社区承办,以王怀民院士为首组建评审委员会,进行研讨评审,面向中国开源行业领域,遴选具有创新性、贡献度和影响力的开源项目、社区、应用场景与开源事件。在评审出的 10 个年度开源项目中,Apache RocketMQ、Apache Seata 成功入选。
199 72
|
5月前
|
人工智能 监控 开发者
阿里云PAI发布DeepRec Extension,打造稳定高效的分布式训练,并宣布开源!
阿里云PAI发布DeepRec Extension,打造稳定高效的分布式训练,并宣布开源!
|
8月前
|
消息中间件 监控 数据可视化
Apache Airflow 开源最顶级的分布式工作流平台
Apache Airflow 是一个用于创作、调度和监控工作流的平台,通过将工作流定义为代码,实现更好的可维护性和协作性。Airflow 使用有向无环图(DAG)定义任务,支持动态生成、扩展和优雅的管道设计。其丰富的命令行工具和用户界面使得任务管理和监控更加便捷。适用于静态和缓慢变化的工作流,常用于数据处理。
Apache Airflow 开源最顶级的分布式工作流平台
|
12月前
|
消息中间件 安全 API
Apache RocketMQ ACL 2.0 全新升级
RocketMQ 作为一款流行的分布式消息中间件,被广泛应用于各种大型分布式系统和微服务中,承担着异步通信、系统解耦、削峰填谷和消息通知等重要的角色。随着技术的演进和业务规模的扩大,安全相关的挑战日益突出,消息系统的访问控制也变得尤为重要。然而,RocketMQ 现有的 ACL 1.0 版本已经无法满足未来的发展。因此,我们推出了 RocketMQ ACL 2.0 升级版,进一步提升 RocketMQ 数据的安全性。本文将介绍 RocketMQ ACL 2.0 的新特性、工作原理,以及相关的配置和实践。
13764 55
|
12月前
|
存储 关系型数据库 MySQL
深度评测:PolarDB-X 开源分布式数据库的优势与实践
本文对阿里云开源分布式数据库 PolarDB-X 进行了详细评测。PolarDB-X 以其高性能、强可用性和出色的扩展能力在云原生数据库市场中脱颖而出。文章首先介绍了 PolarDB-X 的核心产品优势,包括金融级高可靠性、海量数据处理能力和高效的混合负载处理能力。随后,分析了其分布式架构设计,包括计算节点、存储节点、元数据服务和日志节点的功能分工。评测还涵盖了在 Windows 平台通过 WSL 环境部署 PolarDB-X 的过程,强调了环境准备和工具安装的关键步骤。使用体验方面,PolarDB-X 在处理分布式事务和实时分析时表现稳定,但在网络问题和性能瓶颈上仍需优化。最后,提出了改进建
7369 2
|
12月前
|
分布式计算 API 对象存储
Ray是一个开源的分布式计算框架,用于构建和扩展分布式应用。它提供了简单的API,使得开发者可以轻松地编写并行和分布式代码,而无需担心底层的复杂性。
Ray是一个开源的分布式计算框架,用于构建和扩展分布式应用。它提供了简单的API,使得开发者可以轻松地编写并行和分布式代码,而无需担心底层的复杂性。
1901 11
|
关系型数据库 分布式数据库 数据库
PolarDB,阿里云的开源分布式数据库,与微服务相结合,提供灵活扩展和高效管理解决方案。
【7月更文挑战第3天】PolarDB,阿里云的开源分布式数据库,与微服务相结合,提供灵活扩展和高效管理解决方案。通过数据分片和水平扩展支持微服务弹性,保证高可用性,且兼容MySQL协议,简化集成。示例展示了如何使用Spring Boot配置PolarDB,实现服务动态扩展。PolarDB缓解了微服务数据库挑战,加速了开发部署,为云原生应用奠定基础。
521 3
|
关系型数据库 分布式数据库 PolarDB
**PolarDB开源指南:构建分布式数据库集群**踏上PolarDB开源之旅,了解如何从零开始搭建分布式集群
【7月更文挑战第3天】**PolarDB开源指南:构建分布式数据库集群**踏上PolarDB开源之旅,了解如何从零开始搭建分布式集群。采用存储计算分离架构,适用于大规模OLTP和OLAP。先准备硬件和软件环境,包括Linux、Docker和Git。然后,克隆源码,构建Docker镜像,部署控制节点和计算节点。使用PDCli验证集群状态,开始探索PolarDB的高性能与高可用性。在实践中深化学习,贡献于数据库技术创新。记得在安全环境下测试。
259 1

推荐镜像

更多