基于MongoDB的分布式事务处理系统及方法
文献发布时间:2023-06-19 11:35:49
技术领域
本发明涉及数据库分布式事务处理领域,尤其涉及基于MongoDB的分布式事务处理系统及方法。
背景技术
随着企业数据量的不断增长,企业开发应用架构向微服务架构演进,微服务架构将业务模块切分为应用服务,不同的应用服务间通过分布式事务保证数据的一致性。然而传统的分布式事务很难应用于微服务架构中,因此,研究基于微服务架构的分布式事务具有重要的意义。
相比传统关系型数据库,MongoDB的复制集、分片集群的独特设计,使其具有较好的扩展性和可用性。然而MongoDB在一次全局事务处理过程中,会长时间锁定资源,影响业务系统的性能。
如公开号为CN111880908A的专利申请提供了一种分布式事务的处理方法、装置及存储介质,该方法包括:接收分布式事务处理请求,分布式事务处理请求中包括多个处理操作,其中处理操作包括本地处理操作、其他微服务的处理操作的至少一项,根据多个处理操作的关联关系,依次执行多个处理操作得到执行结果,向客户端返回执行结果。通过依次执行多个处理操作确保全局数据的最终一致性,另外,可通过预设的多线程并发处理多个分布式事务处理请求,提高系统整体的吞吐量。虽然该方案可以解决分布式事务处理往往耗时较长的问题,但是不能克服MongoDB分布式事务长期锁定资源的缺陷,因此,需要对分布式事务处理系统进行进一步改进。
发明内容
本发明的目的在于克服现有技术的不足,提供一种基于MongoDB的分布式事务处理系统及方法,基于BASE理论,实现了适用于微服务架构下的最终一致性分布式事务,克服了MongoDB分布式事务长期锁定资源的缺陷。
本发明的目的是通过以下技术方案来实现的:
一种基于MongoDB分布式事务处理系统,包括拦截分析模块、日志生成模块、分支事务控制模块和协调者管理模块。其中,拦截分析模块用于对需要进行事务控制的用户请求进行拦截,构建AST并提取AST中的词语信息,将SQL转换为MongoDB语句。
日志生成模块用于根据转换后的MongoDB语句制作补偿日志,并在补偿日志生成过程中对表资源进行加锁。
分支事务控制模块用于提交分支事务的状态,并在提交事务状态成功后,释放加锁的表资源。
协调者管理模块用于根据参与者的事务提交状态,完成分支事务或回滚事务。
具体的,拦截分析模块包括拦截器、SQL解析器和元数据提取模块;拦截器用于对需要进行事务控制的用户请求进行拦截;SQL解析器用于构建AST;元数据提取模块用于使用访问器提取AST中的谓词和查询类型信息,并与MongoDB映射表进行比对,将SQL转换为MongoDB语句。
具体的,日志生成模块包括前镜像生成模块、后镜像生成模块和日志生成提交模块;前镜像生成模块用于根据转换后的MongoDB语句,重写查询语句,并连接数据库查询需进行操作的Document当前状态,制作前镜像;后镜像生成模块用于执行MongoDB语句得到操作后的结果制作后镜像;日志生成提交模块用于将前镜像和后镜像合并生成回滚日志undo_log,且在整个日志生成提交过程中对表资源进行加锁。
具体的,分支事务控制模块包括本地事务提交模块和状态提交模块;本地事务提交模块用于提交分支事务的状态;状态提交模块用于当成功提交事务状态后,释放被加锁的表资源。
具体的,协调者管理模块包括系统事务协调器模块;系统事务协调器模块用于给参与者事务分配全局XID,并根据参与者的事务提交状态,完成分支事务或回滚事务。
一种基于MongoDB分布式事务处理系统的分布式事务处理方法,包括以下步骤:
步骤一:请求拦截分析,对需要进行事务控制的用户请求进行拦截,使用SQL解析器用于构建AST,同时使用访问器提取AST中的谓词和查询类型信息,并与MongoDB映射表进行比对,将SQL转换为MongoDB语句;
步骤二:补偿日志生成,根据转换后的MongoDB语句,重写查询语句,并连接数据库查询需进行操作的Document当前状态,制作前镜像;同时执行MongoDB语句得到操作后的结果制作后镜像;最后将前镜像和后镜像合并生成回滚日志undo_log,且在整个日志生成提交过程中对表资源进行加锁;
步骤三:事务的状态提交,提交分支事务的状态,若长时间无法向协调者提交成功状态则视为事务执行失败;当成功提交事务状态后,释放被加锁的表资源;
步骤四:分布式事务执行,根据参与者事务提交状态,完成分支事务或回滚事务。
本发明的有益效果:
1.本发明基于2PC的两阶段理念,其中包含协调者和参与者,通过日志补偿的机制减少整体锁表时间,提高系统的可用性和性能,适用于微服务架构。
2.本发明系统具有较好的鲁棒性,鲁棒性对于系统运行的稳定程度具有重要的参考意义,也是系统提供服务的前提。不会因为业务数量的变化而对出现性能抖降的问题。
3.本发明系统具有良好的可用性,当协调者或参与节点不会因为单点故障造成业务长时间阻塞或宕机,且能够快速响应用户请求。
4.本发明系统具有较好的拓展性,以最终一致性事务插件形式部署,通过修改解析规则以及镜像生成原理,即可满足不同数据库使用。
附图说明
图1是本发明的系统功能框图。
图2是本发明实施例的系统整体架构图。
图3是本发明实施例的两阶段时序图。
图4是本发明实施例的第一阶段具体处理流程图。
图5是本发明实施例的二阶段成功提交逻辑示意图。
图6是本发明实施例的服务端控制回滚流程图。
图7是本发明实施例的RPC通信基本架构图。
图8是本发明实施例的SQL拦截解析映射提取时序图。
图9是本发明实施例的日志构建过程示意图。
图10是本发明实施例的分支事务控制基本流程图。
图11是本发明的动态代理基本原理图。
图12是本发明的拦截器数据流向图。
图13是本发明的拦截器调用结构流程图。
图14是本发明的解析器解析流程图。
图15是本发明的AST示例结构图。
图16是本发明的基本映射关系示例图。
图17是本发明的日志生成流程图。
图18是本发明的一阶段事务提交流程图。
图19是本发明的二阶段事务提交流程图。
图20是本发明的异步队列逻辑图。
图21是本发明的协调者集群架构图。
具体实施方式
为了对本发明的技术特征、目的和效果有更加清楚的理解,现对照附图说明本发明的具体实施方式。
MongoDB支持的分布式事务框架主要使用2PC基本原理来满足事务的ACID特性,本身满足强一致,但会导致两阶段提交过程中一直锁表直到整个事务流程完成,很难保证微服务架构下的可用性,因为长时间锁表导致某些单一业务场景(表冲突)性能下降严重。其原生架构图如图32,是非常典型的2PC架构,使用ClockSI进行并发控制。客户端发起请求,通过Mongos进行请求分发,作为MongoDB的路由,可理解为系统中的拦截器和网关,会指定某一分片为协调者,其它分片为参与者,并且将相应的请求发送到对应的分布中。协调者收集参与者的事务状态以完成整个事务过程。
MongoDB中协调者与参与者的事务提交基本流程中,参与者根据分片服务器当前状态进行预提交,若发现快照冲突或者长时间未收到协调者广播则会abort。协调者主要还是进行全局提交或回滚状态的控制,相比传统2PC,增加了超时机制,防止单点阻塞。MongoDB复制集的设计虽然保证了数据库的可用性,但也会导致分布式事务执行过程中还需要将事务状态记录到oplog中,方便副本根据oplog进行复制,这会增加事务处理时间。并且在两阶段提交过程中,仍会长时间对Collection进行锁定(且因为NoSQL中不能用粒度更小的行锁等),当读事务和准备中的写事务发生表冲突时,会给读事务返回WT_PREPARE_CONFLICT状态拒绝访问,需要等待写事务完成,故可用性受到了极大的限制。
针对上述MongoDB分布式事务框架出现的问题,本发明中,如图1所示,提供了一种基于MongoDB分布式事务处理系统,包括拦截分析模块、日志生成模块、分支事务控制模块和协调者管理模块。
具体的,拦截分析模块包括拦截器、SQL解析器和元数据提取模块,拦截器可将需要进行事务控制的用户请求进行拦截,使用SQL解析器构建AST。同时使用访问器提取AST中的谓词、查询类型等信息,与MongoDB映射表进行比对将SQL转换为MongoDB语句,对数据库进行操作。本发明中的元数据提取相当于SQL解析的子模块,从原始的SQL语句中解析出的Statement、projection等即为元数据。如select*from table1 where id= 5。元数据即为table1(表名)Id(字段名)、5(参数)。本发明中构建的AST即抽象语法树(abstract syntaxcode),是源代码的抽象语法结构的树状表示,树上的每个节点都表示源代码中的一种结构。在SQL中的AST上会有各元数据的信息。本发明中构建的AST示例如图15所示。
日志生成模块包括前镜像生成模块、后镜像生成模块和日志生成提交模块。前镜像生成模块对于更新、删除操作,根据系统拦截器解析器以及元数据提取模块中得到的MongoDB语句,重写查询语句,并连接数据库查询需进行操作的Document当前状态,制作前镜像。后镜像生成模块然后执行MongoDB语句得到操作后的结果制作后镜像。日志生成提交模块将前镜像和后镜像合并生成回滚日志(undo_log),整个过程中对表加锁。在本发明中,回滚日志即补偿日志,同时被加锁资源和释放被锁资源中的表为MongoDB语句操作的实际表,例如db.table1.find({})。这样一个语句,会对原始的数据表table1进行操作,这里锁定的就是table1,防止有其它事务同时对table1进行操作而导致结果不正确。
分支事务控制模块包括本地事务提交模块和状态提交模块。本地事务提交模块用于提交分支事务的状态,当该模块长时间无法向协调者提交成功状态则视为事务执行失败。状态提交模块用于当成功提交事务状态后,释放被锁资源。
协调者管理模块包括包含系统事务协调器模块。系统事务协调器模块用于给参与者事务分配全局XID,并根据参与者事务提交状态,成功完成事务或回滚事务。
在本发明的实施例中,分布式事务处理系统分为参与者与协调者,其中参与者部分主要负责SQL拦截、解析与元数据提取、分支注册、全局锁控制、反向SQL镜像生成等。协调者进行全局事务和分支事务的控制等。
因为NoSQL与SQL式操作语句不同,互相并不兼容,所以需要进行不同的适配来满足存储层的相应操作要求,如MongoDB中的相关CRUD语句均为链式,和传统SQL并不一致。除此之外日志与反镜像日志的制作会关系到最终事务的效率,相比原生的MongoDB分布式事务在自带的分片上进行设计。
本实施中以真实业务中的电商系统为例,包含订单、库存、支付服务。以此说明各层基本职能,更加符合系统的真实架构场景。用户进行下单后,请求通过浏览器或者APP发送到网关层,拦截器筛选事务相关的请求,网关根据注册中心的路由信息,将请求推送到对应机器。协调者单独布置为集群,订单服务、库存服务、支付服务作为参与者进行分布式事务。整个事务过程完成后返回到客户端。
如图2所示,从系统整体架构图可知,因为微服务的链式特点(即先创建订单,再检查库存,最后进行支付),不同的微服务处理流程是串行的。在一次全局事务中,一般选取第一个被调用的服务(订单服务)向协调者请求注册一个全局的XID,这个XID相当于一个全局锁以及标识,每个当前分支事务都会带上这个XID进行事务传播,以此来保证原子性与一致性。并且针对一个XID下事务的全局提交与回滚,协调者和事务管理器会协作进行调度。而不同微服务之间的事务传播主要是通过上下文实现。这种方式不仅保证了最终一致性,也使得分支事务在提交状态后可以及时释放锁,增强可用性。相比直接改造MongoDB原生分布式事务,这种插件式分布式事务在工业生产中更加灵活,可扩展性更强,并且更通用的应用到其它数据库中。
本实施例基于BASE理论,实现了适用于微服务架构下的最终一致性分布式事务,弥补了MongoDB分布式事务长期锁定资源的缺陷。通过日志补偿机制,对两阶段提交协议进行优化。两阶段时序图如图3所示,都围绕着补偿日志展开。因为一阶段就完成本地事务的提交,二阶段完成前无法保证隔离性,即系统可能会导致脏读、可重复读、幻读等问题,隔离级别为读未提交,不适用需要保证数据强一致的场景。但在第一阶段不同阶段加锁防止脏写。
第一阶段具体流程如图4。参与者将生成的回滚日志保存到MongoDB数据库中对应的表中,并本地执行业务更新操作。为了保证事务的写隔离,分支必须注册后(即向服务端申请锁)才能提交。否则可能会导致同时操作表而产生脏数据。
当分支注册成功后,释放锁资源,提交当前事务状态,第一阶段正式完成。核心工作包括以下两点:
1)根据输入的SQL进行拦截、解析,映射为MongoDB语法,进而生成相应的执行器SqlExecutor。
2)生成前后镜像生成undo_log,并提交当前分支事务状态给服务端并申请全局锁。
第二阶段协调者使用异步队列处理参与者提交的事务状态。若都成功提交,则协调者会返回成功的信号给所有参与者,参与者通过返回信号中的XID和分支ID从数据库中找到对应undo_log,并异步删除过期的undo_log。二阶段成功提交逻辑如图5所示。
第二阶段若协调者检测都有参与者发送分支提交失败的状态,则协调者会返回回滚的信号给所有参与者。各分支通过XID和分支ID找到对应undo_log,因为一阶段保存了前镜像,前镜像即是在进行业务更新前数据库对应Document的初始状态。通过前镜像中的键值信息,反写镜像后执行。这就是日志补偿的基本思路。
当数据库中数据还原后删除过期的undo_log并向协调者提交回滚成功的状态。当所有参与者都提交完成后,全局事务完成。如图6所示,其展示了服务端控制回滚流程。
RPC是协调者与参与者间的通信手段。RPC即远程过程调用,是一个计算机通信协议。RPC能让用户无感知的使用远程函数。如图7所示为RPC基本流程。对于调用和被调用的服务器,总是对应着有接收器和连接器,类似TCP三次握手,两方需建立连接并使用代理来进行数据传输。为了保证两边数据形式一致,往往需要对数据进行序列化与反序列化保证能解析。
因此,本实施例中采用Java基本通信框架Netty来进行RPC通信,Netty采用NIO同步非阻塞的通信方式,使用I/O多路复用提高相应的性能。
本实施例中,系统的拦截分析模块主要包括SQL拦截器、解析器和元数据提取模块。其中,SQL拦截器是所有SQL的入口程序。因为不同关系型数据库和非关系型数据库的语法差异很大,本实施例为了增强系统的可扩展性,方便系统进行业务分发,设计SQL拦截器与解析器来进行不同SQL的语句解析映射。
本实施例系统中SQL拦截使用Java自身反射代理特性来实现。获取SQL后,使用解析器通过词法分析、语法分析生成AST,使用Visitor拿到关键元数据信息,并根据自定的MongoDB规则映射为MongoDB语句。SQL拦截解析映射提取时序如图8所示。本发明中自定的MongoDB规则如图16所示,通过提取拼接,进行基本的转换映射。
映射后的语句是前后镜像生成的重要依据,本实施例将映射后语句的反写放在第二阶段进行,主要基于以下两个考量:
1)实际业务中80%以上的事务都能成功提交,对于这些事务并不需要进行回滚,一阶段就生成反写镜像会导致资源的浪费。
2)二阶段异步操作过程中,可以释放对线程的占用,提升资源利用率。
SQL拦截通过JAVA自带的切片模式设计,解析器使用Druid来进行解析与元数据的提取,MongoDB语句的映射主要通过操作符判定为CRUD中的哪一种,再提取谓词、表名等信息使用MongoDB Template进行拼接得到最终语句。
本实施例中,系统的日志生成模块的主要功能包括日志的生成与存储,因为MongoDB是使用BSON格式进行数据的存储,因此本实施例把解析器解析后提取出的元数据进行keyvalue嵌套设计,方便后续操作。日志存储常见方案是直接使用文件系统,存储为文件格式,但在当前业务场景下,每个事务流程都需要格外进行一次文件操作,这种方式效率较低。本实施例为了二阶段提交或回滚时能通过XID和分支ID快速查找对应日志,并且减少IO操作的消耗,直接在数据库中建表存放相应的日志信息即可。
日志的生成分为两部分,前镜像和后镜像。首先查询业务请求涉及到的表数据状态(即用find来进行一次扫描),然后执行业务请求对应的MongoDB语句,并保存得出执行后的数据结果。两个结果合并为undo_log。这个日志构建过程如图9所示。
本实施例中,在完成日志生成之后,参与者将分支事务情况向协调者提交,以注册分支信息。并对当前Document加锁,防止这台机器还有其它事务提交导致脏写。注册完成后把分支ID也更新到日志中,并提交用户更新与日志到对应的MongoDB数据库中,至此一阶段结束。当完成上述操作后,每台机器本地提交事务并向协调者上报结果。此时本地事务释放锁并提交分支事务状态给协调者。分支事务控制基本流程如图10所示。
本实施例中,协调者包含系统事务协调器模块。协调者在两阶段提交的第一阶段中,主要负责给参与者事务分配全局XID,方便分支事务提交完成后全局事务的提交以及保证隔离性。并且给已经生成日志的本地事务相应的Collection或者Document加锁,防止后续事务又操作当前表导致脏读等问题的出现。当分支事务注册完成后,将全局事务号和相应分支事务信息保存到数据库中。当二阶段未抛出异常,协调者会根据分支事务提交的不同情况控制全局事务的提交或者回滚,存在两种情况:
1)回滚:当任意分支事务执行失败时,协调者通知各分支事务进行本地回滚。本地事务通过XID以及分支ID可以快速找到其对应的回滚日志。通过回滚日志反写SQL将数据恢复到请求前的状态,并再次把当前状态报告给协调者说明当前已回滚成功。
2)提交:通知参与者异步删除回滚日志。
本实施例除了基本功能的实现,还根据微服务架构的特点,将协调者单独布置为多副本集群,防止宕机单点阻塞,且保证宕机后迅速切换到副本保证整体可用性。
为进一步阐述本发明系统的工作原理,下面本发明将根据系统中参与者和协调者的分工,详细介绍其中包含的模块,以及模块的具体优化、执行流程、设计框图等进行详细的介绍。
本发明系统的参与者分为三个模块,分别是拦截分析模块、日志生成模块、分支事务控制模块。这三个模块主要用于实现SQL拦截与解析、补偿日志的生成、分支事务的管理、全局事务的开启、提交以及回滚信号控制和分布式事务的跨服务实例传播。
拦截分析模块包括系统拦截器、SQL解析器和元数据提取模块。其中应用层的拦截器(Interceptor)基本原理是Java的反射,通过对象名,反射出其属性和方法,本发明基于JDK实现的动态代理最终实现拦截器。动态代理基本原理如图11所示。
本发明将代理的概念进一步抽象,拦截器中可抽象出代理类和委托类(被代理类)。以此将不同业务类型进行分类,其优点在于能实现解耦并且隐藏委托类,底层非常透明。在实际微服务应用中并不是所有业务都需要事务控制,对于需要进行事务处理的业务逻辑进行拦截控制,可以提高系统整体速度,增强系统拓展性,如图12所示,其为拦截器数据流向。用户发出请求,通过网关对业务请求进行分发,网关处的路由信息由注册中心统一控制。注册中心为微服务架构中基本组件,复制路由信息、元数据信息的控制,对于提高集群伸缩性具有重大意义。网关将对应请求发送到给服务上,拦截器将事务相关请求进一步发给插件的解析器进行解析,而不涉及事务的请求不会对插件造成很大的负载压力。
本发明通过拦截器的拦截与判定,可以方便的把需要接入最终一致性事务插件的业务进行分类。并将用户输入传给解析器进行相应SQL的解析。拦截器主要由两个Handler进行控制,分别为preHandle以及postHandle,当用户进行输入时,拦截器调用结构流程如图13所示。
首先prehandle对用户请求进行过滤,判定是否需要进行事务控制(这里通过埋点打标对数据进行标志位的初始化)。如果属于需要接入最终一致性事务插件的,则postHandle从请求的body中拿到相关的SQL语句,并根据不同的请求地址,通过RPC把对应SQL语句发送到对应机器或者集群中,各集群或者机器上的解析器拿到SQL语句后返回成功状态并进行解析工作。
本发明系统的解析器设计过程中,所提到的SQL为标准MySQL,在解析时只能对MySQL进行解析。通过系统拦截器对SQL语句进行拦截。为了对其中的元数据进行提取,就需要使用Parser将SQL分析并构建为语法树AST。解析器解析流程如图14所示。
Parser主要由词法分析和语法分析构成。词法分析分析词语是否有错误,是否能被解析,当无法从中找到对应关系,则无法通过词法分析,说明当前SQL并不符合现有规则或者有相应的词法错误。语法分析就是需要明确SQL的具体含义,即不同的操作符号具体代表的操作。之后便可以得到AST。以SQL语句”select username,age from user where id =1”为例,AST示例结构如图15所示。SELECT、UPDATE、INSERT、DELETE 等操作符统一称为SQLStatement,指示当前操作的类型。fields 即投影,对应着MongoDB的映射,即所需要的列(key)信息。tables即表名,where即SQLObject,conditions统称为SQLExpr。因为AST是树形结构,且元数据与值信息是分层的,能够高效访问提取。
AST中包含着一个SQL语句中的元数据信息以及参数,但为了后续进一步进行SQL的映射和拼接,需要访问器(visitor)对AST进行遍历,提取元数据信息。访问器使用广度优先遍历。通过遍历树就可以取得我们需要的元数据,如谓词、表名、投影、子句等。
在visitor遍历后得到SQL语句中的SQLObject、SQLExpr、SQLStatement后,为了让MongoDB存储层能识别相关操作,还需把相关的SQLObject、SQLExpr、SQLStatement等映射为MongoDB语法形式。SQL的基本结构与MongoDB语法形式有很大区别,基本映射关系示例如图16所示。
通过图16中内容可以知,SQL与MongoDB语法差异巨大,因为关系型数据库行列结构与MongoDB中BSON结构的具有很大区别。parser解析后,visitor可以获知当前为查询、插入、更新或者删除操作,根据不同的操作类型,选取不同的模板类进行处理,使用MongoDBTemplate最终拼接转换为最终MongoDB语法的语句。MongoDB Template是封装基本方法的库包,封装了MongoDB各种操作的函数类,把元数据信息作为参数传入对应操作模板类中,即可重构为MongoDB语句。通过以上操作即可通过MongoDB Driver进行存储层中数据库中Collection的操作。
在本发明的日志生成模块设计过程中,解析器模块通过parser以及语法映射后,得到了用户输入的SQL转换后的MongoDB语法语句。但是日志补偿的基本原理是先找到对应的文档并记录当前对应数据状态;接着执行用户输入的语句,并记录执行后的数据状态;最后保存两种状态并给协调者提交状态。为了得到执行前的数据状态,需要根据解析器模块得到的SQL进行拆分组合得到相应的查询语句,具体原理为:通过谓词WHERE后的参数进行相关匹配与修改。对于CRUD四种操作这里的逻辑也是不同的,即插入操作不需要重写查询语句,前镜像用op:0占位即可,查询操作也不需要重写查询语句,与用户输入一致,更新操作和删除操作需根据用户输入进行查询语句的重写。
在获取到转换后的MongoDB查询语句以及用户输入语句后,需要连接MongoDB(即使用MongoDB本身的存储引擎进行数据的相关操作),并根据前后镜像制作undo_log并提交分支事务获取锁。其日志生成流程如图17所示。
undo_log即本发明核心的补偿日志,是为了快速查找到不同事务组的镜像,不同分支事务的镜像,本发明的undo_log数据结构包含sqlType、tableName、beforeImage和afterImage。sqlType为当前语句的类型(CRUD),根据parser解析出来的Statement得到。tableName即表名,方便二阶段回滚能快速定位表。beforeImage和afterImage即是通过转换后的查询语句得到的数据以及用户输入的语句得到的数据。回滚日志具体结构中包含以下几个信息:
1)_id,这是MongoDB自动生成的_id号,标明每个文档(Document)的唯一序号。_id号具有唯一性的特点,因此也常被用于锁表以及保证业务的幂等性。
2)branchId,向协调者注册的分支号,在二阶段参与者可通过branchId快速查找到对应undo_log,提高整体效率(虽然二阶段异步操作,仍会产生系统资源的消耗)。
3)undoItems,其中保存着前镜像、后镜像以及操作类型的相关信息,以key[1]value进行数据存储,name即是字段名,value即是值,并且保存表名,通过这些信息可以构建出反镜像满足回滚。
4)XID,与branchId一样,方便快速找到日志,并且标志着不同用户组,防止脏写现象的发生。
日志生成完毕后一阶段即将进入尾声,根据2PC的事务架构可知,其容易长时间阻塞的原因在于两阶段都会锁表。而这里的日志补偿完成后,各分支事务(各机器上本地事务)就可以提交并释放锁,此时其它请求就可以操作当前的表了,其最终一致性由二阶段日志控制。
本发明的系统分支事务控制模块设计过程中,为了保证整个事务集的原子性和隔离性,参与者向协调者申请锁来保证本地提交过程中不会被其它事务进行脏写,导致出现数据不一致的问题。
分支事务控制阶段主要进行两个工作,一个是拿到全局锁,主要防止与其它的全局事务冲突导致写冲突,并且提交分支ID给协调者,若二阶段发起回滚请求,参与者可根据分支ID和XID快速定位日志。另一个是提交更新以及undo_log(undo_log为JSON形式,直接建立Collection进行存储)到数据库中,即正式落盘。在提交完成后对于每一个分支事务来说,其实他当前的事务阶段已经结束了,所以这时候就可以释放锁来进行其他事务任务。当然在提交完成后需要通过RPC给协调者发送当前的成功失败状态,这是第二阶段正常完成以及回滚的唯一参考条件。一阶段事务提交流程如图18所示。
在本发明的协调者管理模块设计过程中,协调者主要是根据参与者分支事务的元数据信息,进行相关的注册、提交回滚等。一阶段主要是负责采集各分支事务的事务状态,二阶段则负责控制全局事务以及分支事务各自的逻辑走向。二阶段有两种可能的逻辑,一种是一阶段所有都提交都成功,一种是一阶段有分支事务提交失败,二阶段事务提交流程图如19所示。
分布式事务类型从强一致性转换为最终一致性与异步队列的使用息息相关。异步队列即消息队列,使用额外的线程对队列消息进行消费,如图20所示为异步队列逻辑图4。把任务放到异步队列中后台执行,削峰填谷,可有效减轻高并发场景下的整体负载压力。
当所有分支事务(即各机器上的本地事务都已提交完毕并且向协调者发送信号)状态都为提交成功,因为在一阶段已经完成了数据的落地。协调者在后台建立异步队列,将提交状态异步通过异步队列通知给参与者,参与者删除本地过期的undo_log。
如果提交失败则会回滚,协调者会通知参与者在本地通过undo_log进行回滚,并进行新一轮的一阶段提交。如上流程图所示,有以下步骤:
1)协调者给各参与者发送回滚信号(包含xid和branchId);
2)根据回滚信息中的id,每个参与者找到数据库中相应的undo_log;
3)生成反镜像补偿;
4)继续进行第一阶段工作,上报状态。
反镜像的生成与查询语句的生成类似,以回滚日志中的前镜像和SQL类型为基本点,利用MongoDBTemplate对相应的keyvalue进行拼接,并对操作类型进行反转即可。
为了解决2pc存在的单点故障问题,进一步提高系统可用性,本发明将协调者布置为集群,设置三副本,防止协调者单点故障导致系统整体宕机。协调者集群基本架构图如图21所示。以三台机器为例,每台机器中启动三分片,之间互为副本集。
本发明中,还提供一种基于MongoDB分布式事务处理系统的分布式事务处理方法,包括以下步骤:
步骤一:请求拦截分析,对需要进行事务控制的用户请求进行拦截,使用SQL解析器用于构建AST,同时使用访问器提取AST中的谓词和查询类型信息,并与MongoDB映射表进行比对,将SQL转换为MongoDB语句;
步骤二:补偿日志生成,根据转换后的MongoDB语句,重写查询语句,并连接数据库查询需进行操作的Document当前状态,制作前镜像;同时执行MongoDB语句得到操作后的结果制作后镜像;最后将前镜像和后镜像合并生成回滚日志undo_log,且在整个日志生成提交过程中对表资源进行加锁;
步骤三:事务的状态提交,提交分支事务的状态,若长时间无法向协调者提交成功状态则视为事务执行失败;当成功提交事务状态后,释放被加锁的表资源;
步骤四:分布式事务执行,根据参与者事务提交状态,完成分支事务或回滚事务。
以上显示和描述了本发明的基本原理、主要特征和本发明的优点。本行业的技术人员应该了解,本发明不受上述实施例的限制,上述实施例和说明书中描述的只是说明本发明的原理,在不脱离本发明精神和范围的前提下,本发明还会有各种变化和改进,这些变化和改进都落入要求保护的本发明范围内。本发明要求保护的范围由所附的权利要求书及其等效物界定。
- 基于MongoDB的分布式事务处理系统及方法
- 基于广播信道的分布式事务处理系统及方法