Apache RocketMQ 正式开源分布式事务消息

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

近日,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提供一站式轻量级分布式事务解决方案,用以满足各种场景下的分布式事务需求。

作者介绍:

冯嘉,Apache RocketMQ联合创始人,Linux OpenMessaging标准创始人。阿里巴巴高级技术专家,带领团队、社区打造了中国分布式云计算领域第一个Apache顶级开源中间件项目,创立分布式消息领域的国际标准OpenMessaging。

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

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

原文链接 

本文为云栖社区原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/521219.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何使用阿里云ARMS诊断Java服务端报错问题

摘要: 这是ARMS团队推出的“网站常见问题1分钟定位系列篇”第二文。 我的网站为什么一错再错 网页报错,尤其是5XX错误是互联网应用最常见的问题之一。5XX错误通常发生于服务端。服务端是业务逻辑最复杂,也是整条网络请求链路中最容易出错、出…

.iml文件_jetbrains误删maven 项目.iml文件后的处理方法

jetbrains 打开maven项目, 出现如下提示这个时候打开 Terminal在提示符下输入:mvn idea:module 回车运行,就可以修复。Relationship between .iml file and pom.xml fileThe intelliJ idea doesnt understand the maven project model (POM.x…

亚马逊消费者业务宣布永久关闭 Oracle 数据库,去O新进展;华为发布最新5G全系列解决方案;苹果正研究新设备“智能戒指”……...

戳蓝字“CSDN云计算”关注我们哦!嗨,大家好,重磅君带来的【云重磅】特别栏目,如期而至,每周五第一时间为大家带来重磅新闻。把握技术风向标,了解行业应用与实践,就交给我重磅君吧!重…

vs未能找到程序集platform.winmd_PP体育直播大连人VS恒大:新老8冠王首尾对决竟有十大看点...

北京时间8月25日,中超大连赛区的第7轮较量,广州恒大迎战大连人,恒大取胜即可继续位列榜首,同时获得半程冠军。而对于前6轮不胜的大连人来说,已经被逼上了绝境。虽然大连人晋级争冠组的前景极为渺茫,但一胜难…

Sentinel如何通过限流实现服务的高可用性

摘要: 在复杂的生产环境下可能部署着成千上万的服务实例,当流量持续不断地涌入,服务之间相互调用频率陡增时,会产生系统负载过高、网络延迟等一系列问题,从而导致某些服务不可用。如果不进行相应的流量控制&#xff0c…

京信通信:数据智能为生产调试“增效瘦身”

摘要: “数据驱动测试优化,突破自动测试边界,赋能智慧测试新模式。”——京信智能制造副总经理葛鑫 “进入车间,映入眼帘的是一条长约20 米的 O 型生产线,产线前三名工人和几个机器人正协同工作,将各种元器…

c++代码好玩_一行Python代码能干嘛?快来看看吧!有表白利器哦

python有很多优雅有趣的代码写法,同时还很简短,以至于当我刚开始接触这个编程语言的时候,就爱不释手。而前几天的编程语言榜单中python也超越了java成为了第一,挺替python开心的。python到底有多有趣呢?一行代码告诉你…

探秘HDFS —— 发展历史、核心概念、架构、工作机制 (上)| 博文精选

戳蓝字“CSDN云计算”关注我们哦!作者 | Mr-Bruce转自 | CSDN博客责编 | 阿秃几周前,笔者做了一个与HDFS有关的技术分享,以知识普及为目的,主要分享了Hadoop发展历史、HDFS核心概念、整体架构、工作机制等内容。本文大…

linux CentOS7最小化安装环境静默安装Oracle11GR2数据库(配置数据库监听_09)

修改dbca.rsp响应文件中的重要参数 su - oracle cd response/ vim dbca.rsp本次安装过程中设置了下列参数:(注意下面参数视情况而定,不要照抄,原文件都有说明的) RESPONSEFILE_VERSION "11.2.0" #不能更改 OPERATION_TYPE "…

如何量化考核技术人的 KPI?

摘要: 为什么需要技术KPI? 在业务技术团队,有一个不好的趋势就是团队越来越业务,越来越没有技术味道。每个人都在谈业务,技术大会上在谈业务,周会上在聊业务,周报里写的是业务项目...... 唯独少…

pandas绘图_pandas与seaborn可视化对比小案例

Python网络爬虫与文本数据分析(视频课)之前分享过pandas也是可以作图的,今天复习一下pandas作图,并与seaborn做对比,熟悉下各自绘图的特点。导入用到的库import pandas as pdimport matplotlib.pyplot as pltimport seaborn as sns%matplotli…

docker安装zookeeper_Docker安装Zookeeper以及Zookeeper常用命令

Docker安装Zookeeper下载并运行$ docker search zookeeper # 查看一下镜像$ docker pull zookeeper:3.4.9 # 拉取指定版本zk镜像$ docker images # 查看image ID$ mkdir -p /root/docker/zookeeper/data $ docker run -d -p 2181:2181 -v /root/docker/zookeeper/data:/data/…

复杂 SQL 查询跑不动?DRDS 只读实例来解决!

摘要: 在实际业务生产环境中,业务应用系统在使用 OLTP 数据库将数据进行存储后,均会存在如后台运营类系统进行统计报表分析等场景的复杂 SQL 查询诉求。 背景 在实际业务生产环境中,业务应用系统在使用 OLTP 数据库将数据进行存储…

三年一跳槽、拒绝“唯学历”,火速 Get 这份程序员求生指南!

戳蓝字“CSDN云计算”关注我们哦!作者 | 郭芮责编 | 阿秃根据埃文斯数据公司(Evans Data Corporation)2019 最新统计的数据显示,2018 年全球共有 2300 万软件开发人员,预计到 2019 年底这个数字将达到 2640 万。但在这…

Oracle的instantClient的安装配置(都是64位)

背景:本地没有安装oracle客户端和服务端(最简单) 文章目录一、远程连接方案二、软件下载2.1. 官网下载instantclient2.2. 解压2.3. 位置前移2.4. 创建目录和监听文件2.5. 添加监听信息2.6. 设置以下环境变量2.7. plsql配置2.8. 重启启动一、远…

如何利用阿里视频云开源组件,快速自定义你的H5播放器?

摘要: Aliplayer希望提供一种方便、简单、灵活的机制,让客户能够扩展播放器的功能,并且Aliplayer提供一些组件的基本实现,用户可以基于这些开源的组件实现个性化功能,比如自定义UI和自己App server的交互等等&#xff…

vmware 蓝屏_网络安全小百科--利用微软CVE 2019-0708漏洞让对方系统蓝屏死机

漏洞背景:Windows 系列服务器于 2019 年 5 月 15 号,被爆出高危漏洞,该服务器漏洞利用方式是通过远程桌面端口3389进行攻击的。这个漏洞是今年来说危害严重性最大的漏洞,跟之前的永恒之蓝病毒差不多。2019年9月7日晚上凌晨 1 点左右&#xff…

instantclient使用步骤

1、 解压缩instantclient后(假定目录为:G:\instantclient_11_2_64) 把oracle安装目录下的G:\oracle\product\11.2.0\dbhome_1\NETWORK 文件夹复制到instantclient安装目录, 修改instantclient目录下的NETWORK\ADMIN\tnsnames.ora文…

NLP中的迁移学习

摘要: 迁移学习正在各个领域大展拳脚,NLP领域正在受到冲击! 在我们之前的文章中,我们展示了如何使用CNN与迁移学习为我们自己创建图片构建分类器。今天,我们介绍NLP中迁移学习的最新趋势,并尝试进行分类任…

Linux Shell脚本专栏_服务器系统配置初始化脚本_01

文章目录一、服务器系统配置初始化1. 设置时区并同步时间① 脚本编写②脚本说明2. 禁用selinux① 脚本编写②脚本说明3. 关闭防火墙① 脚本编写②脚本说明4. 历史命令显示操作时间① 脚本编写②脚本说明5. 禁止root远程登录① 脚本编写②脚本说明6. 禁止定时任务发送邮件① 脚本…