在后台系统架构时,越来越多的项目采用了分布式架构,与传统的单体式架构相比,分布式架构具有多种优势:分布式服务中的某一个服务只是系统的一部分功能,当服务不可用时,不影响整个系统;单个服务的更新、部署,无需重新部署整个系统;各系统可以在各自的环境中,采用不同的技术开发,方便技术的更新换代,代码的整合优化。
但分布式架构的引入,也带来了新的挑战,对于单体架构模式,分布式架构需要通过REST或者RPC等形式进行服务间通讯,需要考虑被调用方的故障及消息丢失等情况。此外,系统运行发布也变得更加麻烦,需要做好各部分的服务监控,个服务间的事务一致性也需要额外的维护,代码逻辑更加复杂,增加了开发难度。
为了规范事务管理,X/OPEN组织开始推行数据库与事务管理器的借口标准——XA协议,目前,Oracle、informix、DB2和Sybase等各大商业数据库厂家都提供了对XA协议的支持,mysql数据库也在5.8版本后,支持了XA协议。XA协议采用两阶段提交方式来管理分布式事务,并提供数据库与事务管理器之间进行通讯的标准接口。
为了实现分布式事务,需要使用两阶段提交协议:
阶段一:开始向事务涉及到的全部资源发送提交前信息。此时,事务涉及到的资源还有最后一次机会来异常结束事务。如果任意一个资源决定异常结束事务,则整个事务取消,不会进行资源的更新。否则,事务将正常执行,除非发生灾难性的失败。为了防止会发生灾难性的失败,所有资源的更新都会写入到日志中。这些日志是永久性的,因此,这些日志会幸免于难并且在失败之后可以重新对所有资源进行更新。
阶段二:只在阶段一没有异常结束的时候才会发生。此时,所有能被定位和单独控制的资源管理器都将开始执行真正的数据更新。 在分布式事务两阶段提交协议中,有一个主事务管理器负责充当分布式事务协调器的角色。事务协调器负责整个事务并使之与网络中的其他事务管理器协同工作。 为了实现分布式事务,必须使用一种协议在分布式事务的各个参与者之间传递事务上下文信息,IIOP便是这种协议。这就要求不同开发商开发的事务参与者必须支持一种标准协议,才能实现分布式的事务。
CAP理论:
Consistency(一致性), 数据一致更新,所有数据变动都是同步的
Availability(可用性), 好的响应性能
Partition tolerance(分区容忍性) 可靠性
定理:任何分布式系统只可同时满足二点,没法三者兼顾。
BASE理论:
跨数据库两段提交事务:2PC (two-phase commit), 2PC is the anti-scalability pattern (Pat Helland) 是反可伸缩模式的,JavaEE中的JTA事务可以支持2PC。因为2PC是反模式,尽量不要使用2PC,使用BASE来回避。BASE模型反ACID模型,完全不同ACID模型,牺牲高一致性,获得可用性或可靠性:
Basically Available基本可用。支持分区失败(e.g. sharding碎片划分数据库)
Soft state软状态 状态可以有一段时间不同步,异步。
Eventually consistent最终一致,最终数据是一致的就可以了,而不是时时高一致。
BASE思想的主要实现有
1.按功能划分数据库
2.sharding碎片
柔性事务与刚性事务:
刚性事务是指严格遵循ACID原则的事务, 例如单机环境下的数据库事务.
柔性事务是指遵循BASE理论的事务, 通常用在分布式环境中, 常见的实现方式有:
①两阶段提交
②TCC补偿型提交
③基于消息的异步确保型
分布式事务解决方案:
基于XA协议的两阶段提交方案:
两阶段提交是分布式事务传统解决方案,当一个事务跨越多个节点时,为了保持事务ACID特性,需要引入一个作为协调者来统一掌控所有节点(称作参与者)的操作结果并最终指示这些节点是否要把操作结果进行真正的提交(比如将更新后的数据写入磁盘等等)。因此,二阶段提交的算法思路可以概括为:参与者将操作成败通知协调者,再由协调者根据所有参与者的反馈情报决定各参与者是否要提交操作还是中止操作。
两阶段提交中的第二阶段,协调者需要等待所有参与者发出yes请求,或者一个参与者发出no请求后,才能执行提交或者中断操作。这会造成长时间同时锁住多个资源,造成性能瓶颈,如果参与者有一个耗时长的操作,性能损耗会更明显。两阶段提交,不仅要锁住参与者的所有资源,而且要锁住协调者资源,开销大,效率很低,对高并发很不友好。
TCC补偿型提交
TCC补偿型提交,也是两阶段提交的一个变种。TCC提供了一个编程框架,将整个业务逻辑分为三块:Try、Confirm和Cancel三个操作。以在线下单为例,Try阶段会去扣库存,Confirm阶段则是去更新订单状态,如果更新订单失败,则进入Cancel阶段,会去恢复库存。
TCC补偿对应用的侵入性强,业务逻辑的每个分支都需要实现try、confirm、cancel三个操作,事务改造成本高、实现难度较大。并且需要按照网络状态、系统故障等不同的失败原因实现不同的回滚策略。为了满足一致性的要求,confirm和cancel接口必须实现幂等。总之,TCC就是通过代码人为实现了两阶段提交,不同的业务场景所写的代码都不一样,复杂度也不一样,因此,这种模式并不能很好地被复用。
基于消息的异步确保型
通过将一系列同步的事务操作变为基于消息执行的异步操作,避免了分布式事务中的同步阻塞操作的影响。事务追求最终一致性,中间有可能不一致。消息中间件在系统中扮演一个重要的角色,所有的事务消息都需要通过它来传达,所以消息中间件也需要支持 HAC 来确保事务消息不丢失。该方案执行周期较长,适合对实时性要求不高的场景。
执行步骤如下:
1、MQ发送方发送远程事务消息到MQ Server;
2、MQ Server给予响应, 表明事务消息已成功到达MQ Server;
3、MQ发送方Commit本地事务;
4、若本地事务Commit成功,则通知MQ Server允许对应事务消息被消费;若本地事务失败,则通知MQ Server对应事务消息应被丢弃;
5、若MQ发送方超时未对MQ Server作出本地事务执行状态的反馈, 那么需要MQ Servfer向MQ发送方主动回查事务状态, 以决定事务消息是否能被消费;
6、当得知本地事务执行成功时, MQ Server允许MQ订阅方消费本条事务消息。
方案案例:
MQ:
RabbitMQ遵循了AMQP规范,用消息确认机制来保证:只要消息发送,就能确保被消费者消费来做到了消息最终一致性。而且开源,文档丰富,是实现分布式事务的良好载体。
GTS:
GTS是一款分布式事务中间件,由阿里巴巴中间件部门研发,可以为微服务架构中的分布式事务提供一站式解决方案。
GTS的核心优势:
性能超强
GTS通过大量创新,解决了事务ACID特性与高性能、高可用、低侵入不可兼得的问题。单事务分支的平均响应时间在2ms左右,3台服务器组成的集群可以支撑3万TPS以上的分布式事务请求。
应用侵入性极低
GTS对业务低侵入,业务代码最少只需要添加一行注解(@TxcTransaction)声明事务即可。业务与事务分离,将微服务从事务中解放出来,微服务关注于业务本身,不再需要考虑反向接口、幂等、回滚策略等复杂问题,极大降低了微服务开发的难度与工作量。
完整解决方案
GTS支持多种主流的服务框架,包括EDAS,Dubbo,Spring Cloud等。
有些情况下,应用需要调用第三方系统的接口,而第三方系统没有接入GTS。此时需要用到GTS的MT模式。GTS的MT模式可以等价于TCC模式,用户可以根据自身业务需求自定义每个事务阶段的具体行为。MT模式提供了更多的灵活性,可能性,以达到特殊场景下的自定义优化及特殊功能的实现。
容错能力强
GTS解决了XA事务协调器单点问题,实现真正的高可用,可以保证各种异常情况下的严格数据一致。
LCN:
LCN是国产开源的分布式事务处理框架。LCN即:lock(锁定事务单元)、confirm(确认事务模块状态)、notify(通知事务)。LCN的实现是基于3PC的算法,结合TCC的补偿机制。
LCN分布式事务框架的核心功能是对本地事务的协调控制,框架本身并不创建事务,只是对本地事务做协调控制。因此该框架与其他第三方的框架兼容性强,支持所有的关系型数据库事务,支持多数据源,支持与第三方数据库框架一块使用(例如 sharding-jdbc),在使用框架的时候只需要添加分布式事务的注解即可,对业务的侵入性低。LCN框架主要是为微服务框架提供分布式事务的支持,在微服务框架上做了进一步的事务机制优化,在一些负载场景上LCN事务机制要比本地事务机制的性能更好,4.0以后框架开方了插件机制可以让更多的第三方框架支持进来。
特点:
①支持各种基于spring的db框架
②兼容SpringCloud、Dubbo、motan
③使用简单,低依赖,代码完全开源
④基于切面的强一致性事务框架
⑤高可用,模块可以依赖RPC模块做集群化,TxManager也可以做集群化
⑥支持本地事务和分布式事务共存
⑦支持事务补偿机制,增加事务补偿决策提醒
⑧添加插件拓展机制
MQ追求最终一致性,但对代码的侵入性太高,开发、维护的代码量太大,逻辑复杂,不适合在项目中大量使用。从性能分析,GTS要优于LCN,但GTS处于收费状态,LCN目前已更新到第五版本,支持三种模式,分别是LCN模式,TCC模式,TXC模式,可根据需要自行配置。