分布式事务总结
分布式事务总结
事务
事务的定义
事务提供一种机制将一个活动涉及的所有操作纳入到一个不可分割的执行单元,组成事务的所有操作只有在所有操作均能正常执行的情况下方能提交,只要其中任一操作执行失败,都将导致整个事务的回滚。简单地说,事务提供一种"要么什么都不做,要么做全套(All or Nothing)"机制。
数据库本地事务
ACID
1. Atomicity 原子性
代码要么全部完成,要么全部不完成。
2. Consistency 一致性
事务执行成功,那么所有变化(一般指数据)均正确操作。
3. Isolation 隔离性
在并发环境下,不同事务操作相同数据,每个事务都有各自完整的数据空间。事务不会查看到中间数据。
4. Durability 持久性
事务只要成功结束,那么对数据库数据的更新便会永久保存下来。
InnoDB实现原理
1. InnoDB 是 mysql 的一个存储引擎。
2. 事务的 ACID 是通过 InnoDB 的日志和锁来保证的。
1. 隔离性通过数据库锁来保证。
2. 原子性和一致性通过UndoLog来保证。
1. UndoLog:在操作任何数据前,将数据备份到一个地方(数据存储备份的地方叫做UndoLog)。然后进行修改,如果事务执行失败了,那么系统可以利用备份数据恢复到事务执行前的状态。
3. 持久性通过RedoLog来保证。
1. RedoLog:记录新数据的备份,在事务提交前,只要将RedoLog持久化即可,不需要将数据持久化。当系统崩溃时,系统会根据RedoLog的内容,将数据更新至最新状态。
分布式事务
分布式事务的定义
一次大的操作由不同的小的操作组成,而不同的小操作在不同的服务器或者容器内。分布式事务需要保证这些小操作要么全部成功,要么全部失败。
为什么要使用分布式事务
1. 微服务与SOA等服务架构的兴起
2. 单机不能满足业务需要
3. 数据量太大,导致需要分库分表,分布在不同机房
分布式事务的基础
CAP
CAP定理又称布鲁尔定理,这三者不可兼得。
1. C Consistency 一致性
所有数据备份,在同一时刻是否同样的值
2. A Availability 可用性
集群中的部分节点出现故障,集群整体是否还能相应客户端读写
3. P Partition tolerance 分区容错性
分区相当于对通信的时限要求,系统如果不能在指定时限内达成数据一致性,就意味着发生了分区,需要在 C 与 A 之间选择。
CAP三者不能共有。
1. CA 理论上不可能存在。由于网络无法100%可靠,故分布式系统中必定会有分区。分区发生时,为了保证 C,这个时候一定要拒绝请求,但是 A 不允许。
2. CP 放弃可用性,追求强一致
3. AP 放弃一致性(强一致性),追求分区容错性和可用性。BASE也是根据 AP 的拓展
BASE
1. Basically Available 基本可用
分布式系统在出现故障时,允许损失部分可用功能,保证核心功能可用。
2. Soft state 软状态
允许系统中存在中间状态,这个状态不影响系统可用性,这里指的是CAP中的不一致。
3. Eventually consistent 最终一致性
最终一致是指经过一段时间后,所有节点数据都将会达到一致。
BASE解决了CAP中理论没有网络延迟,在BASE中用软状态和最终一致,保证了延迟后的一致性。BASE和 ACID 是相反的,它完全不同于ACID的强一致性模型,而是通过牺牲强一致性来获得可用性,并允许数据在一段时间内是不一致的,但最终达到一致状态。
分布式事务的解决方案
2PC
第一阶段:事务管理器要求每个涉及到事务的数据库预提交(precommit)此操作,并反映是否可以提交.
第二阶段:事务协调器要求每个数据库提交数据,或者回滚数据。
优点
1. 尽量保证了数据的强一致,实现成本较低,在各大主流数据库都有自己实现,对于MySQL是从5.5开始支持。
缺点
1. 单点问题:事务管理器在整个流程中扮演的角色很关键,如果其宕机,比如在第一阶段已经完成,在第二阶段正准备提交的时候事务管理器宕机,资源管理器就会一直阻塞,导致数据库无法使用。
2. 同步阻塞:在准备就绪之后,资源管理器中的资源一直处于阻塞,直到提交完成,释放资源。
3. 数据不一致:两阶段提交协议虽然为分布式数据强一致性所设计,但仍然存在数据不一致性的可能,比如在第二阶段中,假设协调者发出了事务commit的通知,但是因为网络问题该通知仅被一部分参与者所收到并执行了commit操作,其余的参与者则因为没有收到通知一直处于阻塞状态,这时候就产生了数据的不一致性。
TCC
1. Try阶段:尝试执行,完成所有业务检查(一致性),预留必须业务资源(准隔离性)
2. Confirm阶段:确认执行真正执行业务,不作任何业务检查,只使用Try阶段预留的业务资源,Confirm操作满足幂等性。要求具备幂等设计,Confirm失败后需要进行重试。
3. Cancel阶段:取消执行,释放Try阶段预留的业务资源 Cancel操作满足幂等性Cancel阶段的异常和Confirm阶段异常处理方案基本上一致。
与2PC区别
1. 2pc 和3pc 是依靠mysql xa 实现的,是db 层实现(就是直连mysql),tcc 业务层实现符合soa理念,解耦。
2. TCC属于业务上的分段提交,Try,confirm,cancel都是对应的一段业务逻辑的操作,先预留资源,预留成功后进行确认,不成功就取消,例如转账先冻结资金,进行一系列的余额各方面的检查,发现符合条件就对账户对应的资金状态改为冻结,确认阶段修改状态为扣除,取消的话就把冻结的资金加回原账户,其对应的数据库的操作每段都是一个完整的事物;2PC是属于数据库层面的,先进行prepare,然后逐个进行commit或者rollback,不和具体业务逻辑挂钩,TCC的应用范围更广,不一定是事物关系数据库,也可能操作的KV数据库,文档数据库,粒度也可以随着具体业务灵活调整,性能更好。
本地消息表
此方案的核心是将需要分布式处理的任务通过消息日志的方式来异步执行。
对于本地消息队列来说核心是把大事务转变为小事务。用100元去买一瓶水的例子。
1. 当你扣钱的时候,你需要在你扣钱的服务器上新增加一个本地消息表,你需要把你扣钱和写入减去水的库存到本地消息表放入同一个事务(依靠数据库本地事务保证一致性。
2. 这个时候有个定时任务去轮询这个本地事务表,把没有发送的消息,扔给商品库存服务器,叫他减去水的库存,到达商品服务器之后这个时候得先写入这个服务器的事务表,然后进行扣减,扣减成功后,更新事务表中的状态。
3. 商品服务器通过定时任务扫描消息表或者直接通知扣钱服务器,扣钱服务器本地消息表进行状态更新。
4. 针对一些异常情况,定时扫描未成功处理的消息,进行重新发送,在商品服务器接到消息之后,首先判断是否是重复的,如果已经接收,在判断是否执行,如果执行在马上又进行通知事务,如果未执行,需要重新执行需要由业务保证幂等,也就是不会多扣一瓶水。
本地消息队列是BASE理论,是最终一致模型,适用于对一致性要求不高的。实现这个模型时需要注意重试的幂等。
MQ事务
RocketMQ 对 MQ 事务进行了封装。具体内容可以参考链接。
Saga事务
Saga其实是30年前的一篇数据库论文里提到的一个概念。在论文中一个Saga事务就是一个长期运行的事务,这个事务是由多个本地事务所组成, 每个本地事务有相应的执行模块和补偿模块,当saga事务中的任意一个本地事务出错了, 可以通过调用相关事务对应的补偿方法恢复,达到事务的最终一致性。
具体可以看以下链接:
来源:
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: