分布式事务背景
随着互联网的快速发展,软件系统由原来的单体应用转变为分布式应用。
分布式系统会吧一个应用系统拆分为可独立部署的多个服务,因此需要服务与服务之间远程协作才能完成事务操作。
这种分布式系统环境下由不同的服务之间通过网络协作完成事务称之为分布式事务。
简单理解就是,一个任务需要调用A接口、B接口、C接口。ABC接口都在不同服务器上。
如果A成功插入数据了,B成功修改数据了,C操作异常了,需要回滚A和B。
分布式事务基础理论
CAP理论
cap是三个词语的缩写,分别是:一致性、可用性、分区容忍性
一致性是指写操作后的读操作可以读取到最新的数据状态,当数据分别在多个节点上,从任意结点读取到是数据都是最新的状态。
如何实现一致性?
1、由于存在的数据同步的过程,写操作会响应会有一定的延迟。
2、为保证数据一致性会对资源暂时锁定,待数据同步完成释放锁定资源。
3、如果请求数据同步失败的节点则返回错误信息,一定不会返回旧数据,
可用性是指任何事物操作都可以得到响应的结果,且不会出现响应超时或响应错误。
从数据库接收到的数据查询的请求则立即能响应数据查询结果。所有请求都有响应。
分区容忍性是指分布式系统的各个节点部署在不同的子网,这就是网络分区,不可避免的出现由于网络问题而导致结点之间的通信失败,此时任可以对外提供服务。
其中一个节点挂掉不影响另外一个节点对外提供服务。
如何实现分区容忍性?
1、尽量使用异步取代同步操作。
2、其中一个节点挂掉从其他节点提供服务。
分区容忍性是分布式系统具备的基本能力。
CAP组合方式
在所有分布式事务场景中不会同时具备CAP三个特性,因为在具备了P的前提下C和A是不能共存的
当满足P的前提下,C和A是存在矛盾的,因为C一致性会加上锁,那A可用性要及时得到数据,但是被锁上了,所以存在矛盾。
AP组合方式
放弃一致性,最求分区容忍性和可用性,这是很多分布式系统设计的选择。
CP组合方式
放弃可用性,追求一致性和分区容忍性,我们的zookeeper其实就是追求的强一致。
CA组合方式
放弃分区容忍性,即不进行分区,不考虑网络不通或者节点挂掉的情况。那么系统将不再是分布式系统。关系型数据库就满足CA。
总结:一个分布式系统最多只能同时满足一致性、可用性和分区容忍性这三项中的两项。它可以作为我们进行架构设计、技术选择的考量标准。
对于大多数互联网场景,一般都会做出:保证可用性和分区容忍性,舍弃强一致性,最终保证一致。
BASE理论
BASE理论是CAP中的AP的一个扩展,通过牺牲强一致性来获取可用性,当出现故障的时候允许部分不可用但要保证核心部分可用。
允许数据在一段时间内是不一致的,但最终达到一致的状态。满足BASE理论的事务,我们称之为:柔性事务。
基本可用:分布式系统中,允许损失一部分可用功能,保证核心功能可用。
软状态:不要求强一致性,可以允许系统存在中间状态,比如订单的支付中,数据同步中,成功这些状态。
最终一致:最终在过一段时间后,所有数据都会进行同步达到一致。
分布式事务解决方案2PC
什么是2PC
2pc指的是两阶段提交协议,是将整个事务流程分为两个阶段,准备阶段,提交阶段。(目前oracle,mysql等关系型数据都提供两阶段事务)
准备阶段:事务管理器给每个参与者发送Prepare消息,每个数据canyuz都在本地执行事务。并写本地的Undo/Redo日志,此时事务没有提交
(Undo日志是记录修改前的数据,用于数据库回滚;Rodo日志是记录修改后的数据,用于提交事务后写入数据文件)
提交阶段:如果事务管理器收到了参与者的执行失败或者超时消息时。直接给每个参与者发送回滚(Rollback)消息;否则,发送提交(Commitr)消息。
参与者根据事务任务管理器的指令执行提交或者回滚操作。并释放事务处理过程中使用的锁资源。必须在最后阶段释放锁资源。
XA方案
2PC的传统方案是在数据库层面实现的,为了统一标准奸商行业内不必要的对接层本,需要制定标准化的处理模型以及对接接口(DTP)
通过TM事务管理器,负责协调事务。
基于数据库的XA协议来实现2PC又称为XA。
整个2PC的事务流程涉及到三个角色AP、RM、TM。AP指的是2PC分布式事务的应用程序。RM资源数据库,具有单独事务。TM指的是事务管理监视器。
通过TM控制RM的事务来实现。
Seata方案
Seata是由阿里中间件团队发起的开源项目Fescar.
Seata工作的应用层的一个中间件,性能较好。且不长时间占用连接资源。
对业务无侵入性。
事务协调器(TC):他负责维护全局事务的运行状态,接收TM指令发起的全局事务提交和回滚。
事务管理器(TM):事务管理器,它负责开启一个全局事务,并最终向TC发起全局提交或全局回滚的指令。
控制分支事务(RN):负责分支事务,状态会比,接收事务协调器的指令,驱动本地分支事务。
传统2PC方案RM实际上在数据库层,RM本质上就是数据库自身,通过XA实现。而Seata的RM是以Jar包的方式实现。
项目集成Seata开启全局事务:
@GlobalTrabsactuibal
可靠消息最终一致性
当事务的发起方执行完本地事务后并发起一条消息。事务参与方一定能够解释消息并处理事务成功。此方案强调的是只要消息发给事务参与方最终事务要达成一致。
需要解决下面问题:
1、保证本地事务与消息发送的原子性。
2、事务参与方需要保证接收到的消息可靠。
3、消息重复消费的问题。
本地消息表方案:
在本地建立一个消息表,每次操作数据库的操作,在消息表里增加一条记录。
然后启动一个定时任务,定时去扫描消息表日志,发送给消息队列。
如何保证消费者一定能消费?这里可以使用MQ的ack机制。如果消费者接收到消息并且业务处理完成后向MQ发送ack(确认消息)
RocketMQ事务消息实现方案:
应用发送方,先发送本地操作消息给MQ,但是状态不是提交状态,MQ回应成功后。
应用方commit操作的时候自动发送消息让MQ修改成功提交状态。
如果MQ一致没有收到确认的commit。会对应用进行会查事务状态。