1. 基础理论
1.1 事务特性(ACID)
这种特性简称刚性事物
- 原子性(A):所谓的原子性就是说,在整个事务中的所有操作,要么全部完成,要么全部不做,没有中间状态。对于事务在执行中发生错误,所有的操作都会被回滚,整个事务就像从没被执行过一样。
- 一致性(C):事务的执行必须保证系统的一致性,就拿转账为例,A有500元,B有300元,如果在一个事务里A成功转给B50元,那么不管并发多少,不管发生什么,只要事务执行成功了,那么最后A账户一定是450元,B账户一定是350元。
- 隔离性(I):所谓的隔离性就是说,事务与事务之间不会互相影响,一个事务的中间状态不会被其他事务感知。
- 持久性(D):所谓的持久性,就是说一单事务完成了,那么事务对数据所做的变更就完全保存在了数据库中,即使发生停电,系统宕机也是如此。
1.2 分布式理论知识
1.2.1 CAP理论
CAP
由Eric Brewer
在研发搜索引擎、分布式web缓存时得出的关于数据一致性(consistency
)、服务可用性(availability
)、分区容错性(partition-tolerance
)的猜想:
- 数据一致性(consistency):如果系统对一个写操作返回成功,那么之后的读请求都必须读到这个新数据;如果返回失败,那么所有读操作都不能读到这个数据,对调用者而言数据具有强一致性(
strong consistency
) (又叫原子性 atomic、线性一致性linearizable consistency
) - 服务可用性(availability):所有读写请求在一定时间内得到响应,可终止、不会一直等待
- 分区容错性(partition-tolerance):在网络分区的情况下,被分隔的节点仍能正常对外服务
1.2.2 Base理论
BASE
理论是指,Basically Available
(基本可用)、Soft-state
( 软状态/柔性事务)、Eventual Consistency
(最终一致性)。是基于CAP
定理演化而来,是对CAP
中一致性和可用性权衡的结果。核心思想:即使无法做到强一致性,但每个业务根据自身的特点,采用适当的方式来使系统达到最终一致性。
- 基本可用:指分布式系统在出现故障的时候,允许损失部分可用性,保证核心可用。但不等价于不可用。比如:搜索引擎0.5秒返回查询结果,但由于故障,2秒响应查询结果;网页访问过大时,部分用户提供降级服务,等。
- 软状态:软状态是指允许系统存在中间状态,并且该中间状态不会影响系统整体可用性。即允许系统在不同节点间副本同步的时候存在延时。
- 最终一致性:系统中的所有数据副本经过一定时间后,最终能够达到一致的状态,不需要实时保证系统数据的强一致性。最终一致性是弱一致性的一种特殊情况。
BASE
理论面向的是大型高可用可扩展的分布式系统,通过牺牲强一致性来获得可用性。ACID
是传统数据库常用的概念设计,追求强一致性模型。
1.2.3 柔性事务满足BASE理论(基本可用,最终一致)
主要分为:
- 两阶段型
- 补偿型
- 异步确保型
- 最大努力通知型
1.3 XA接口
XA
是一个分布式事务协议,由Tuxedo
提出。XA
中大致分为两部分:事务管理器和本地资源管理器。其中本地资源管理器往往由数据库实现,比如Oracle、DB2
这些商业数据库都实现了XA
接口,而事务管理器作为全局的调度者,负责各个本地资源的提交和回滚。
1.4 JTA
作为java
平台上事务规范JTA(Java Transaction API)
也定义了对XA
事务的支持,实际上,JTA
是基于XA
架构上建模的,在JTA
中,事务管理器抽象为javax.transaction.TransactionManager
接口,并通过底层事务服务(即JTS
)实现。像很多其他的java
规范一样,JTA
仅仅定义了接口,具体的实现则是由供应商(如J2EE
厂商)负责提供,目前JTA
的实现主要由以下几种:
J2EE
容器所提供的JTA
实现(JBoss
)- 独立的
JTA
实现:如JOTM
,Atomikos
.这些实现可以应用在那些不使用J2EE
应用服务器的环境里用以提供分布事事务保证。如Tomcat,Jetty
以及普通的java
应用。
1.5 二阶段提交协议(2PC)
二阶段提交协议主要分为两个阶段:准备阶段和提交阶段。
协调者询问参与者是否能执行事务提交操作。如果参与者能够执行事务的提交,先执行事务操作,然后返回YES
,如果没有成功执行事务操作,就返回NO
。
当协调者接收到所有的参与者的反馈之后,开始进入事务提交阶段。如果所有参与者都返回YES
,那就发送COMMIT
请求,如果有一个人返回NO
,那就返送rollback
请求。
二阶段提交协议的第一阶段准备阶段不仅仅是回答YES or NO
,还是要执行事务操作的,只是执行完事务操作,并没有进行commit
或是roolback
。一旦事务执行之后,在没有执行commit
或者roolback
之前,资源是被锁定的,这会造成阻塞。
2PC
在执行过程中可能发生协调者或者参与者突然宕机的情况,在不同时期宕机可能有不同的现象。2PC
协议中,如果出现协调者和参与者都挂了的情况,有可能导致数据不一致。
为了解决这个问题,衍生出了3PC
。
1.6 三阶段提交协议(3PC)
3PC
把2PC
的准备阶段一分为二,这样三阶段提交就有CanCommit
、preCommit
、DoCommit
三个阶段,在第一阶段询问所有参与者是否可以执行事务操作,并不在本阶段执行事务操作,当协调者收到所有参与者都返回yes
时,在第二阶段才执行事务操作,然后在第三阶段执行commit
或rollback
.
3PC为什么比2PC好?
- 直接分析协调者和参与者都挂的情况,看上去和二阶段提交的那种数据不一致的情况的现象是一样的,但仔细分析所有参与者的状态的话就会发现其实并不一样。我们假设挂掉的那台参与者执行的操作是commit。那么其他没挂的操作者的状态应该是什么?他们的状态要么是prepare-commit要么是commit。因为3PC的第三阶段一旦有机器执行了commit,那必然第一阶段大家都是同意commit。所以,这时,新选举出来的协调者一旦发现未挂掉的参与者中有人处于commit状态或者是prepare-commit的话,那就执行commit操作。否则就执行rollback操作。这样挂掉的参与者恢复之后就能和其他机器保持数据一致性了。
- 所以,再多引入一个阶段之后,3PC解决了2PC中存在的那种由于协调者和参与者同时挂掉有可能导致的数据一致性问题。
2. TX-LCN(同步场景)
2.1 TX-LCN介绍与特点
TX-LCN介绍:
LCN
通讯是基于TCP
长连接的socket
通讯,TxManager与事务控制方是基于netty
框架完成的。该协议只描述参与Socket
通讯的协议。LCN
分布式事务框架其本身并不创建事务,而是基于对本地事务的协调从而达到事务一致性的效果。LCN
核心采用3PC
机制,采用强一致性方案,保证了事务的一致性。
框架优点:
- 兼容
SpringCloud
、Dubbo
; - 兼容
rpc
降级熔断 - 使用简单,低依赖,代码完全开源;
- 基于切面的强一致性事务框架;
- 高可用,模块可以依赖
Dubbo
或SpringCloud
的集群方式做集群化,TxManager
也可以做集群化; - 支持本地事务和分布式事务共存;
框架缺点:
- 代理的连接需要随事务发起方一共释放连接,增加了连接占用的时间;不适用于热点数据和异步场景。
2.2 核心步骤
1.创建事务组:是指在事务发起方开始执行业务代码之前先调用TxManager创建事务组对象,然后拿到事务标示GroupId的过程。
2.添加事务组:添加事务组是指参与方在执行完业务方法以后,将该模块的事务信息添加通知给TxManager的操作。
3.关闭事务组:是指在发起方执行完业务代码以后,将发起方执行结果状态通知给TxManager的动作。当执行完关闭事务组的方法以后,TxManager将根据事务组信息来通知相应的参与模块提交或回滚事务。
2.3 事务控制原理
TX-LCN
由两大模块组成, TxClient
、TxManager
,TxClient
作为模块的依赖框架,提供TX-LCN
的标准支持,TxManager
作为分布式事务的控制放。事务发起方或者参与反都由TxClient
端来控制。
TxClient
的代理连接池实现了javax.sql.DataSource
接口,并重写了close
方法,事务模块在提交关闭以后TxClient
连接池将执行"假关闭"操作,等待TxManager
协调完成事务以后在关闭连接。
对于代理连接池的优化:
- 自动超时机制:任何通讯都有最大超时限制,参与模块在等待通知的状态下也有最大超时限制,当超过时间限制以后事务模块将先确认事务状态,然后再决定执行提交或者回滚操作,主要为了给最大资源占用时间加上限制。
- 智能识别创建不同的连接 对于只读操作、非事务操作LCN将不开启代理功能,返回本地连接对象,对于补偿事务的启动方将开启回滚连接对象,执行完业务以后马上回滚事务。
- LCN连接重用机制 当模块在同一次事务下被重复执行时,连接资源会被重用,提高连接的使用率。