初识分布式事务
前置概念了解
本地事务
事务是一组操作组成的一个操作序列, 当所有的操作都正常执行之后才能被全部提交. 只要有任意一次的操作失败了, 都将回滚所有的操作.
简单的说就是, 要么全部做完, 要么一个都别做.
举个例子: 一个点餐问题, 大致会产生以下六个步骤操作, 这些操作都可以被认为是缺一不可的, 但凡缺少了其中的一个环节, 整个点餐过程就失去了一些意义

事务的ACID特性
A(Atomicity)原子性 : 遵循本地事务特性的原子性, 保证多个操作能作为一个最小执行单元执行.
C(Consistency)一致性 : 同大多分布式系统中的一致性概念
I(Isolation)隔离性 : 大多指数据库事务的隔离等级, 不同隔离等级会在并发读写时导致不一样的问题.
D(Durability)持久性 : 事务操作完成后写入磁盘的持久化操作.
CAP定理
CAP是2000年在PODC上提出的一个猜想. 2002年在MIT被证明. (证明是严格的证明, 讨论了在两个互相矛盾的请求到达彼此连接不通的两个不同的分布式节点)
- 一致性(Consistency)
- 可用性(Availability)
- 分区容错性(Partition tolerance)

BASE
经过了长时间的实践, 人们发现通过CAP定理来维护事物的ACID特性需要付出很大的特性, 总结出来一套弱化的事务特性. 服务化中,更多的是提升 A 以及 P,在这个过程中不可避免的会降低对 C 的要求
- 基本可用(Basically Available):系统能够基本运行、一直提供服务。
- 软状态(Soft-state):系统不要求一直保持强一致状态。
- 最终一致性(Eventual consistency):系统需要在某一时刻后达到一致性要求。
分布式事务产生场景
随着互联网的发展, 简单的单机提供单一服务已经不能满足当下需求.
随着大数据时代来临, 庞大的数据量单一数据库已经不能完成很好的服务.
一个业务功能可能需要跨越多个服务和操作多个数据库. 分布式事务就是为了保证不同服务器之间的数据一致性.
数据库分库
一个数据对应多个数据库微服务架构
一个业务跨越多个服务, 同时操作多个数据库
分布式事务解决方案
2PC
这是最简单的分布式事务解决方案, 也是其他解决方案的基础思维.
两个角色: 协调者(TM Transaction Manager), 参与者(RM Resource Manager)
投票阶段
TM通知各RM准备提交事务.
- 如果RM可以提交事务则给TM回复确定
- 如果RM无法提交则回复否定
提交阶段
TM根据所有RM的结果决定是提交还是回滚事务.
- 如果全部为确认响应, 发起提交请求, RM收到请求后提交事务.
- 如果有否定响应, 则发起回滚请求, RM收到请求后回滚事务.

优点
- 尽量高效的确保了数据的强一致性, 但不是100%一致.
缺点
- TM故障: RM会一直阻塞, 事务资源被锁定, 无法继续完成事务操作和后续操作.
- 同步阻塞: 在等待TM回复的过程中一直占用公共资源, 导致第三方访问公共资源阻塞.
- 数据不一致:
- 提交阶段TM发起提交请求后, 出现网络异常导致部分RM无法收到请求, 产生不一致数据.
- 如果协调者在第二阶段发送提交请求之后挂掉,而唯一接受到这条消息的参与者执行之后也挂掉了,即使协调者通过选举协议产生了新的协调者并通知其他参与者进行提交或回滚操作的话,都可能会与这个已经执行的参与者执行的操作不一样。

3PC
改动点
- 引入超时机制.
- 新增一个阶段解决由于TM故障引起的阻塞问题.
第一阶段 CanCommit
等同于2PC的投票阶段
第二阶段 PreCommit
TM判断各RM的响应轻快判断是否做预提交操作(PreCommit), 有两种可能:
如果所有RM返回确认响应, 执行事务预提交
- 向所有RM发送
PreCommit请求 - RM收到后将事务操作写入事务日志, 进行事务操作持久化.
- 成功完成了事务操作持久化后, 给TM确认响应, 等待下一步指令
- 向所有RM发送
假如有RM返回了否认响应, 或者TM等待超时, 执行中断请求.
- TM向所有RM发送Abort请求.
- RM收到Abort请求后执行事务中断.
第三阶段 DoCommit
进行真正的事务提交
- 执行提交
- TM收到所有RM来自PreCommit阶段的确认响应后,将状态更改为(预提交->)提交, 向所有RM发送确认提交请求.
- RM收到确认提交请求后提交事务并释放事务资源.
- RM完成后向TM发送确认请求.
- TM收到所有RM在DoCommit阶段的确认后, 确认事务完成.
- 中断事务
- TM没有收到所有RM来自PreCommit阶段的确认响应, (或是收到了RM的超时响应) (或者自身超时), 向所有的RM发送Abort请求.
- RM收到Abort请求后, 根据事务操作日志中的记录回滚事务并释放事务资源.
- RM完成回滚后, 向TM发送回滚完成确认响应.
- TM收到RM的回滚确认后, 确认事务中断.

问题
- 已经解决了
- 由于TM和某些RM挂掉导致的数据一致性问题
- TM单点故障问题
- 但是仍然存在
- 在DoCommit阶段如果TM执行事务中断, 部分RM未能收到请求默认执行事务提交而导致的数据一致性问题.

可见2PC和3PC都无法保证100%数据一致性.
其他解决方案
2PC和3PC是分布式事务实现中较为简单的两种实现方案. 也有不少系统投入使用这两种方案. (据说阿里有在支付宝业务中使用两阶段提交)
还有更多的分布式事务解决方案, 例如:
- TCC
- Saga
- 使用消息队列实现消息事务
- 本地消息表
有空的话会再了解其他方案.
参考资料
- CAP- 阮一峰
- 微软研究院的
consensus-on-transaction-commit论文 - Rachid guerraoui 的
Revisiting the relationship between non-blocking atomic commitment and consensus论文



