一.项目中遇到的问题
A服务:修改数据库 --> 调用B服务 (加Transaction)
B服务:修改数据库
A是主调用,B是从调用,允许两边暂时不一致,要求最终一致性
。
上面做法可能存在的问题:
1.A服务修改数据库,调用B服务,B服务成功修改数据库,返回Http code给A服务,此时网络抖动,A服务没有收到B服务的返回,请求超时,跨服务调用抛异常,A服务修改数据库回滚,导致数据不一致;
2.A服务修改数据库,调用B服务,B服务成功修改数据库,返回Http code给A服务,此时A挂掉重启,A服务修改数据库回滚,B服务修改数据已生效,导致数据不一致;
3.A服务修改数据库,调用B服务,B服务成功修改数据库,返回Http code给A服务,A服务收到返回信息,向数据库commit事务时失败,A服务修改数据库回滚,导致数据不一致。
在微服务中,不可以避免的会遇到跨服务调用修改数据库的应用场景,此时需要根据具体的业务场景选择合适的分布式事务方案。
二.CAP原理
CAP含义:
- Consistency:一致性,客户端任何时候看到各节点的数据都是一致的。
- Availability:可用性,任意时刻系统都可以提供读写服务,每个请求都能接受到一个响应,无论响应成功或失败。
- Partition Tolerance:分区容错性,由于网络问题,各个服务之间的通信都有可能中断,形成多个分区,系统在任意的网络分区情况下都必须正常的工作。
对于一个分布式系统
来说,涉及到多节点通信,分区故障是不可避免的,同时为了保证系统的横向拓展和可用,P 是一个基本要求,CAP 三者中,只能根据系统要求在 C 和 A 两者之间做权衡,并且要想尽办法提升 P。
- AP(高可用&&分区容错):
允许至少一个节点更新状态会导致数据不一致,即丧失了C性质(一致性)。会导致全局的数据不一致。 - CP(一致&&分区容错)
为了保证数据一致性,将分区一侧的节点设置为不可用,那么又丧失了A性质(可用性)。分区同步会导致同步时间无限延长(也就是等数据同步完成之后才能正常访问)
三.一致性
强一致性
:当更新操作完成之后,任何多个后续进程或者线程的访问都会返回最新的更新过的值。这种是对用户最友好的,就是用户上一次写什么,下一次就保证能读到什么。根据 CAP 理论,这种实现需要牺牲可用性。
弱一致性
:系统并不保证后续进程或者线程的访问都会返回最新的更新过的值。系统在数据写入成功之后,不承诺立即可以读到最新写入的值,也不会具体的承诺多久之后可以读到。
最终一致性
:弱一致性的特定形式。系统中所有的副本经过一段时间的异步同步
之后,最终能够达到一个一致性的状态,也就是说在数据的一致性上存在一个短暂的延迟。
几乎所有的互联网系统采用的都是终一致性,只有在实在无法使用最终一致性,才使用强一致性,比如,对于决定系统运行的敏感数据,需要考虑采用强一致性,对于与钱有关的支付系统或金融系统的数据,需要考虑采用事务。也就是说能够使用最终一致性的业务就尽量使用最终一致性,因为强一致性会降低系统的可用性。
四.分布式事务的解决方案
1.两阶段提交/XA
两阶段提交协议
,将全局是拆分为两个阶段来执行:
- 阶段一:准备阶段,各个本地事务完成本地事务的准备工作
- 阶段二:执行阶段,各个本地事务根据上一阶段执行结果,进行提交或回滚。
XA
就是通信中间件和事务管理器间联系的接口规范,定义了用于通知事务开始、提交、终止、回滚等接口,各个数据厂商都必须实现这些接口。
劣势:
1.单点故障,协调者挂了,早成各本地事务死锁;
2.各个本地事务互相等待,锁定周期长
,任一事务出现故障,容易造成死锁。
2.TCC
- Try:对各个服务的资源做检测以及对资源进行锁定或者预留。
- Confirm:在各个服务中执行实际的操作。
- Cancel:如果任何一个服务的业务方法执行出错,那么这里就需要进行补偿,就是执行已经执行成功的业务逻辑的回滚操作。
适用于与交易、支付
有关的场景,严格保证分布式事务全部成功,要么全部自动回滚,严格保证资金的正确性,保证在资金上不会出现问题,运行效率高,性能好
。
劣势:
1.代码侵入,需要人为编写代码实现try,confirm,cancel,代码入侵较多
2.开发成本高,一个业务需要拆分为3个步骤,业务代码复杂
3.安全性考虑,如果cancel动作执行失败,就无法回滚,需要引入重试机制,要考虑重试的幂等问题
3.可靠消息服务
将分布式事务拆分成一系列的本地事务,保证最终一致性
,时效性较差,适用于一个主业务+多个从业务,从业务执行失败,不会导致主业务的回滚。
基本原理:
- 事务发起者A执行本地事务
- 事务发起者A通过MQ将需要执行的事务消息发送给事务参与者B
- 事务参与者B接收到消息后执行本地事务
优势:
- 业务相对简单
- 多个本地事务结合,资源锁定周期短,性能好
劣势:
- 代码入侵
- 严重依赖MQ的可靠性
- 消息发送者可以回滚,但消息参与者无法引起事务回滚
- 事务失效性差,取决于MQ消息发送是否及时,还有消息参与者的执行情况
4.AT模式
可以简单理解为简化版本的TCC模式,不需要人工写补偿代码,只需要写基本的业务SQL即可,适用代价低。
AT 模式是一种无侵入的分布式事务解决方案。在 AT 模式下,用户只需关注自己的“业务 SQL”,用户的 “业务 SQL” 作为一阶段,框架(Seata)会自动生成事务的二阶段提交和回滚操作。
5.Saga模式
Saga 是一种补偿协议
,分布式事务执行过程中,依次执行各参与者的正向操作,如果所有正向操作均执行成功,那么分布式事务提交。如果任何一个正向操作执行失败,那么分布式事务会退回去执行前面各参与者的逆向回滚操作,回滚已提交的参与者,使分布式事务回到初始状态。
Saga 正向服务与补偿服务也需要业务开发者实现。因此是业务入侵的。Saga 模式下分布式事务通常是由事件驱动的,各个参与者之间是异步执行的,Saga 模式是一种长事务解决方案
。
优势:
适合需要保证事务最终一致性
的业务系统。事务参与者可能是其它公司的服务或者是遗留系统的服务,无法进行改造和提供 TCC 要求的接口,可以使用 Saga 模式。
劣势:
业务入侵,复杂度高,无法保证事务的原子性和隔离性(上图的事务一T1执行完之后,其他事务是可以读取到最新的修改值)
6.XA、TCC、AT、Saga比较
- XA模式是分布式强一致性的解决方案,但性能低而使用较少。
- TCC 模式是高性能分布式事务解决方案,适用于核心系统等对性能有很高要求的场景。
- AT 模式是无侵入的分布式事务解决方案,适用于不希望对业务进行改造的场景,几乎0学习成本。
- Saga 模式是长事务解决方案,适用于业务流程长且需要保证事务最终一致性的业务系统,Saga 模式一阶段就会提交本地事务,无锁,长流程情况下可以保证性能,多用于渠道层、集成层业务系统。事务参与者可能是其它公司的服务或者是遗留系统的服务,无法进行改造和提供 TCC 要求的接口,也可以使用 Saga 模式。