持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天,点击查看活动详情
一、概念
一个分布式事务就是一个需要在多台机器或者单台机器操作不同的数据库执行的不同任务的集合,他需要保证这些任务要么同时执行成功要么同时执行失败。
对于本地事务来说,通过Spring自带的事务注解@Transaction可以很好实现ACID特性。在分布式事务中,基于CAP和Base理论分别有强一致分布式解决方案和最终一致分布式解决方案。目前在互联网领域中是很难保证其严格一致的,一般保证的是最终一致性的。
二、理论
2.1CAP理论
C-Consistency(一致性):对某个指定的客户端来说,读操作保证能够返回最新的写操作结果
A-Availability(可用性):非故障的节点在合理的时间内返回合理的响应(不是错误和超时的响应)
P-Partition-Tolerance(分区容错性):当出现网络分区后,系统能够继续“履行职责”(分布式系统必备的基本能力)
鱼与熊掌不可兼得---CA、CP、AP
2.2Base理论
Basically Available(基本可用):分布式系统在出现故障的时候,允许损失部分可用性,即保证核心可用。比如电商大促,降级
Soft State(软状态):允许系统存在中间状态,而该中间状态不会影响系统整体可用性。比如MySQL Replication的异步复制,包裹生成
Eventual Consistency(最终一致性):系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。比如下单购物,库存占用
BASE理论是对CAP中一致性和可用性权衡的结果,即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性
2.3一致性模型
强一致性:要求无论更新操作是在哪个数据副本上执行,之后所有的读操作都要能获得最新的数据。对于单副本数据来说,读写操作是在同一数据上执行的,容易保证强一致性。对多副本数据来说,则需要使用分布式事务协议
弱一致性:在这种一致性下,用户读到某一操作对系统特定数据的更新需要一段时间,我们将这段时间称为"不一致性窗口"
最终一致性:是弱一致性的一种特例,在这种一致性下系统保证用户最终能够读取到某操作对系统特定数据的更新(读取操作之前没有该数据的其他更新操作)。"不一致性窗口"的大小依赖于交互延迟、系统的负载,以及数据的副本数等
三、解决方案
3.1强一致性分布式事务解决方案
基于CAP理论,要求在任意时刻查询参与全局事务的各节点的数据都是一致的。
DTP模型(全局事务模型)
DTP模型是X/Open组织定义的一套分布式事务标准,这套标准主要定义了实现分布式事务的规范和API,具体的实现则交给相应的厂商来实现。Mysql、Oracle、Informix、DB2和Sybase均支持。性能问题,国内使用较少。
2PC模型(二阶段提交模型)
问题:(1)同步阻塞,(2)单点故障,(3)数据不一致
3PC模型(三阶段提交模型)
3PC模型主要解决了单点故障问题,并减少了事务执行过程中产生的阻塞现象。但是会导致数据不一致(资源管理器长时间没有接收到事务管理器的doCommit消息会自动提交)
3.2最终一致性分布式解决方案
基于BASE理论,不要求参与事务的各节点数据时刻保持一致,允许存在中间状态,只要在一段时间后,能够达到数据的最终一致性状态即可。即柔性事务
柔性事务模式
| 服务模式 | 示意图 | 描述 |
|---|---|---|
| 可查询操作 | 操作接口:执行业务逻辑,完成业务处理查询接口:查询本次执行结果的接口(需要支持全局的唯一标识) | |
| 幂等操作 | 操作接口:支持幂等,只要请求参数相同,执行多次的结果总是和初次结果一致(实现重试) | |
| 可补偿操作 | 操作接口:执行业务逻辑,完成业务处理补偿接口:用于业务补偿,抵消或部分抵消正向业务操作的业务结果,Compensate操作需满足幂等性 | |
| TCC操作 | Try阶段- 完成所有业务一致性检查- 预占必要的资源Confirm阶段:- 执行业务逻辑,完成业务处理(依赖上述try阶段预占的资源)Cancel阶段:- 释放预占资源- 回滚数据到初始状态 |
TCC解决方案
通用性TCC解决方案
场景:由于从业务服务是同步调用,其结果会影响到主业务服务的决策,因此通用型TCC分布式事务解决方案适用于执行时间确定且较短的业务
补偿性TCC解决方案
场景:由于存在回滚补偿失败的情况,补偿型 TCC分布式事务解决方案只适用于一些并发冲突较少或者需要与外部交互的业务,这些外部业务不属于被动型业务,其执行结果会影响主业务服务的决策
可靠消息最终一致性解决方案
保障事务发起方一定能够将消息发送出去,否则就本地事务回滚或者人工干预
基于本地消息表
增加定时任务,将发送失败或者待发送的轮询发送到消息中间件中
优点:
- 使用消息中间件在多个服务之前传递消息数据,在一定程度上避免了分布式事务的问题
缺点:
- 无法保证各个服务节点之间数据的强一致性。
- 消息表会耦合到业务库中,需要额外手动处理很多发送消息的逻辑,不利于消息数据的扩展。如果消息表中存储了大量的消息数据,会对操作业务数据的性能造成一定的影响。
- 消息发送失败时需要重试,事务参与方需要保证消息的幂等。
- 增加定时任务,对于发送失败消息进行二次发送