之前分享了分布式事务的实现方案,今天我们来对比总结一下:
概述
在构建现代分布式系统时,维持跨多个服务的数据一致性是一项艰巨的任务。想象一下,你正在在线商城上购物,准备为GDP贡献自己的一份力量。在你按下"提交"按钮的那一刻,幕后发生了什么?系统需要同时完成两项操作:在库存服务中减少商品数量和在订单服务中创建订单记录。在单体架构中,这些操作会在同一个事务内完成,但分布式系统中的复杂性远远超出这个范围。
深入理解ACID与CAP
在传统的数据库事务领域,我们依赖ACID来确保数据的完整性和一致性。
ACID特性 解释 原子性(Atomicity) 事务中的所有操作要么全部成功执行,要么全部失败回滚,就像是一个不可分割的"原子"单位。一旦事务开始,就保证其中的操作要么全部完成,要么一个也不做。 一致性(Consistency) 事务必须保证数据库从一个一致性状态转移到另一个一致性状态。事务执行前后,所有数据库的规则都必须应用,保证数据库数据的正确性和逻辑一致性。 隔离性(Isolation) 并发执行的事务之间不应该互相影响。每个事务都像是在一个隔离的环境中执行,它的执行不会被其他事务干扰,同样也不会干扰到其他事务。 持久性(Durability) 一旦事务提交,它对数据库的改变就应该是永久的。即使发生故障,数据库也应该能够恢复到事务提交时的状态。
然而,当这些概念应用到分布式系统时,我们需要重新思考它们的含义。这就是CAP理论登场的时刻:在分布式系统中,我们不可能同时实现一致性(C)、可用性(A)和分区容错性(P)。
CAP告诉我们,在分布式系统中,不可能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition Tolerance)。具体来说:
- 一致性(Consistency):在任何分布式节点读取的数据都是一样的。
- 可用性(Availability):每个请求总能在有限时间内得到响应,不保证获取的数据为最新。
- 分区容错性(Partition tolerance):系统部分节点无法通信的情况下,其余节点形成"网络分区"时也能继续提供服务。
在分布式系统中,网络分区是无法避免的。因此,系统设计通常需要在一致性和可用性之间做出选择(AP或者CP) 。这个选择直接关系到分布式事务的处理方式,因为事务机制需要确保跨多个节点的操作一致性,同时也希望系统能对外提供高可用服务。
完全遵循CP 可能会导致可用性的损失。这就引出了BASE理论,它强调基本可用性、软状态和最终一致性,为分布式系统提供了另一种思考数据一致性的方式。
BASE理论提出了一种与CAP理论不同的权衡方法。它更侧重于可用性,允许数据在分布式系统的不同节点间存在一定程度的不一致,但最终会达到一致状态。当应用ACID属性到分布式系统时,我们通常遵循BASE原则,即基本可用(Basically Available)、软状态(Soft state)和最终一致性(Eventually consistent)。
解决方案
基于CAP及BASE理论,有多种策略可以帮助我们实现不同级别的数据一致性:
- 刚性事务 :基于CP,遵循ACID,对数据要求强一致性。
- XA协议:基于数据库层面的分布式事务协议,主要分为两阶段、三阶段。主流的诸如Oracle、MySQL等数据库均已实现了XA接口
- 柔性事务 :基于AP,遵循BASE,允许一定时间内不同节点的数据不一致,但要求最终一致。
- 最大努力通知:最大努力通知它在事务主动方增加了消息校对的接口,如果事务被动方没有接收到消息,此时可以调用事务主动方提供的消息校对的接口主动获取。
- 本地消息表:本地消息表的方案最初是由 eBay 提出,核心思路是将分布式事务拆分成本地事务进行处理。
- 可靠消息:基于 MQ 的分布式事务方案其实是对本地消息表的封装,先发送一个半消息,本地事务执行后再进行确认。
- TCC: TCC(Try-Confirm-Cancel)又被称补偿事务,TCC与2PC的思想很相似,但2PC是应用于在数据库层面,TCC则在应用层面的,需要我们编写业务逻辑来实现。
- SAGA:Saga是由一系列的本地事务构成。每一个本地事务在更新完数据库之后,会发布一条消息或者一个事件来触发Saga中的下一个本地事务的执行。如果一个本地事务因为某些异常失败,Saga会反向执行这个失败的事务之前成功提交的所有事务的补偿操作。
我们通过一张图来详细对比下:
总结
方案 | 概述 | 使用场景 |
---|---|---|
XA事务 | 依据两阶段、三阶段提交协议进行分布式事务管理 | 需要强一致性的场景,如金融系统 |
最大努力通知 | 不保证ACID特性,尽力而为 | 对一致性要求不高,但要求高可用性的场景 |
本地消息表 | 结合数据库记录表,通过记录表保证操作和消息发送的原子性 | 异步确保操作和消息一致性的场景 |
TCC | 业务上分为Try, Confirm/Cancel两个阶段,先预占资源再确认 。业务上保障 | 对一致性要求高,可明确定义补偿操作的场景 |
SAGA | 将长事务拆分为一系列小事务,处理失败通过补偿事务反向回滚 | 长事务处理,尤其是微服务架构下的业务流程处理 |
可靠消息(RocketMQ) | 通过消息服务保证分布式事务的最终一致性,先发送一个半消息,本地事务执行后再进行确认 | 需要保证消息不丢失并最终处理的异步通信场景 |
Seata | 阿里的分布式统一解决方案,通过TC、TM、RM组件协调分布式事务各分支,支持AT、TCC、SAGA、XA模式 | 支持多种分布式事务场景,适用于大多数微服务架构 |
通过深入学习这些概念和解决方案,我们不仅了解了分布式事务的复杂性,还学会了如何在实际应用中做出恰当的技术选择。那么遇到不同的业务述求时你知道该如何选择合适的分布式事务处理方法了吗?