分布式事务

1、什么是事务?
数据库事务(简称事务,Transaction)是指数据库执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成(由当前业务逻辑的多个不同操作构成)。
事务拥有四个特性,习惯上被称为ACID特性:
原子性:事务作为一个整体被执行,包含在其中的对数据库的操作,要么全部被执行,要么全部都不执行。
一致性:事务应确保数据库的状态从一个一致状态转变为另一个一致状态,一致状态指数据库中的数据应满足完整性约束。除此之外,一致性应满足事务的中间状态不能被观察到。
隔离性:多个事务并发执行时, 一个事务的执行不影响其他事务的执行,如同只有这一个操作在被数据库所执行一样。
持久性:已被提交的事务对数据库的修改应该永久保存在数据库中。在事务结束时,此操作将不可逆转。
2、本地事务
如果将一个单一的服务操纵作为一个事务,那么整个服务操作只能涉及一个单一的数据库资源,这类基于单个服务单一数据库资源访问的事务,称为本地事务。在这里插入图片描述
3、分布式事务
分布式事务指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于位于不同的分布式系统的不同节点之上,且属于不同的应用,分布式事务需要保证这些操作要么全部成功、要么全部失败。总结来说,分布式事务就是为了保证不同数据库的数据一致性。
在这里插入图片描述
4、事务的作用
保证各个事务参与者的事务一致性,也就是数据一致性。
5、CAP定理
C:一致性,即数据一致性。对某个指定的客户端来说,读操作能返回最新的写操作。对于数据分布在不同节点上的数据来说,如果在某个节点更新了数据,那么在其他节点如果都能读取到这个最新的数据,那么就称为强一致性;如果有某个节点没有读取到最新数据,那就是分布式不一致。
A:可用性,保证每个服务都可用。非故障的节点在合理的时间内返回合理的响应(不是错误和超时响应)。可用性的两个关键一个是合理的时间、一个是合理的响应。
P:网络分区容错性,每个服务不在同一个网络内,整个服务仍可用。当出现网络分区后,整个系统仍能够继续工作。比如一个系统集群有多台机器,有一台机器网络出现故障,整个集群仍然可以正常工作。
CAP不能同时存在,在分布式系统中,网络无法100%可靠,网络分区是一个必然现象。如果我们选择CA架构,当发生分区现象时,为了保证C数据一致性,这时必须拒绝请求,那么这样整个服务就不可用了,与A矛盾,所以分布式系统理论上不可能是CA架构,只能是CP或者AP架构。
Zookeeper是CP架构,要求数据强一致性,一旦出现网络分区,导致数据不一致,整个服务就不可用;Eureka是AP架构,即使数据不一致,整个服务仍可用。
CAP中选择其中两个,并不是要放弃第三个,比如选择CP,并不是要放弃A。因为P出现的概率很小,大部分时间仍要保证CA。就算网络分区出现了,也要为A做准备,比如通过一些日志手段等。
6、分布式事务解决方案
6.1基于XA协议的两阶段提交(2PC)
两阶段提交协议中,涉及到两种角色。一个事务协调者,负责协调多个参与者进行事务投票及提交或回滚;多个事务参与者,即本地事务执行者。
处理步骤有两个:
(1)投票阶段:协调者将通知事务参与者准备提交或取消事务,然后进入表决过程。参与者将告知协调者自己的决策:同意(事务参与者本地事务执行成功,但未提交)或取消(本地事务执行故障)。
(2)提交阶段:收到参与者的通知后,协调者再向参与者发出通知,根据反馈情况决定各参与者是否要提交还是回滚。
在这里插入图片描述在这里插入图片描述
如果任一资源管理器在第一阶段返回准备失败,那么事务管理器会要求所有资源管理器在第二阶段执行回滚操作。通过事务管理器的两阶段协调,最终所有资源管理器要么全部提交、要么全部回滚,最终状态都是一致的。
优点:尽量保证了数据的强一致性,适合对数据强一致性要求很高的关键领域。
缺点:牺牲了可用性,对性能影响比较大,不适合高并发高性能场景。
6.2补偿(代码补偿)事务(TCC)
TCC将事务分为3个操作(写3个方法控制事务),也叫3PC,Try – Confirm – Cancel。和两阶段提交有点类似,Try为第一阶段,尝试检查当前操作是否可执行;Confirm - Cancel为第二阶段,确认执行业务操作,实际提交数据,不做任何业务检查,Try成功,Confirm必定成功,需要保证幂等性,Cancel为取消执行业务操作,实际回滚数据,需保证幂等性。
其核心在于将业务分为两个操作步骤完成,通过对业务逻辑的分解来实现分布式事务。
在这里插入图片描述
当所有try()方法均执行成功时,对全局事务进行提交,即由事务管理器调用每个微服务的confirm()方法。当任一个try()方法失败,由事务管理器调用每个微服务的cancel()方法对全局事务进行回滚。
优点:比2PC实现和流程简单
缺点:数据一致性较差,TCC属于应用层的一种补偿方式,需要程序员在实现的时候写很多补偿代码,还存在非幂等问题。
6.3本地消息表(异步确保)-事务最终一致性
其核心思想是将分布式事务拆分成本地事务进行处理。
在这里插入图片描述
基本思路是:
消息生产方,需要额外建一个消息表,并记录消息发送的状态。消息表和业务数据要在一个事务里提交,也就是它们要在一个数据库里面。然后消息会经过MQ发送到消息的消费方,如果消息发送失败,会进行重发。
消息消费方,需要处理这个消息,并完成自己的业务逻辑。此时如果本地事务处理成功,就表名已经处理成功了,如果处理失败,则重试执行。如果是业务上的失败,可以给消息生产方发送一个业务补偿消息,通知生产方进行回滚操作。
生产方和消费方定时扫描本地消息表,把还没处理完成的消息或者失败的消息再发送一遍。
优点:避免了分布式事务,实现了最终一致性,不会出现像2PC那样复杂的实现,也不会像TCC那样可能出现确认或回滚不了的情况。
缺点:增加了消息表,会耦合到业务系统中。
6.4 MQ事务消息-事务最终一致性
阿里的RocketMQ支持事务消息,类似于二阶段提交。其大致思路为:
在业务方法内要想消息队列提交两次请求,一次发送消息和一次确认消息。如果确认消息发送失败了,RocketMQ会定期扫描消息集群中的事务消息,这时发现了Prepared消息,它会向消息发送者确认,生产方需要实现一个check接口,RocketMQ会根据发送端设置的策略来决定是回滚还是继续发送确认消息。这样就确保了消息发送于本地事务同时成功或同时失败。
在这里插入图片描述
优点:避免了分布式事务,实现了最终一致性,不需要依赖本地数据库事务。
6.5 Seata
Seata是阿里巴巴开源的一套一站式分布式事务解决方案。Seata解决分布式事务问题,有两个设计初衷,(1)对业务无侵入,即减少技术架构上的微服务化所带来的分布式事务问题对业务的侵入,(2)高性能,减少分布式事务解决方案所带来的性能消耗。
Seata中有两种分布式事务实现方案,分别是AT和TCC。
AT模式可以看作是2PC的改进型,它的效率变得非常高,对业务是无侵入式的,AT模式主要关注多数据库访问的数据一致性问题。Seata AT模式是基于XA事务演进而来的一个分布式事务中间件,XA是一个基于数据库实现的分布式事务协议,本质上和两阶段提交一样,需要数据库支持。Seata AT模式有3个角色:
Transaction Coordinator(TC):事务协调器,维护全局事务的运行状态,负责协调并决定全局事务的提交或回滚。
Transaction Manager™:控制全局事务的边界,负责开启一个全局事务,并最终发起全局提交或全局回滚的决议。
Resource Manager(RM):控制分支(本地)事务,负责分支注册、状态汇报(投票),并接收事务协调器的指令,驱动分支事务的提交或回滚。
在这里插入图片描述
AT模式流程:RM首先将本地事务信息注册到TC上面,TC就知道了本地事务管理器。事务在本地执行,执行成功后并不会提交事务,而是把本地事务的执行状态投票给TC,如果所有的投票都是预提交(成功),TC会通知RM提交事务,如果有一个投票失败,TC则通知RM回滚事务。
详细流程:
使用Seata AT模式需要在与业务相关的每个数据库中手动添加一张undo_log表。
在第一阶段,Seata会替换掉原有的数据源,使用Seata里面的代理数据源ProxyDataSource,这个代理数据源会执行两个操作,第一次执行业务流程操作,第二次执行日志记录。Seata将这两个操作捆绑到同一个事务中,即业务操作和日志记录保证了同时成功或同时失败。在执行业务时,Seata的代理数据源会对业务的SQL进行解析,之后会从数据库中将要进行操作的原始数据取出保存到undo_log表中,然后执行业务SQL,执行后的数据也会生成新的快照保存到undo_log表,之后会锁定该条记录,保证只能读不能改,防止了被别的事务修改,然后会立刻释放当前的事务,这样就完成了一个本地事务操作,然后将事务操作的状态汇报给TC。而且它几乎是同时提交了修改前和修改后的数据,比2PC的两阶段提交提高了效率。
在这里插入图片描述
在第二阶段,TC接收到本地事务提交的汇报,如果决议是全局提交,TC会通知RM完成事务提交,同时异步删除日志记录,并释放锁。如果决议是全局回滚,TC会通知本地事务全部回滚,并通过XID(多线程的情况下,开启全局事务时会给每个线程生成一个唯一的全局ID,并将该ID一并发送给TC,用来使当前线程找到自己对应的数据)和Branch ID找到相应的回滚日志记录(因为在第一阶段加了行锁,所以不用担心这里的数据被修改),通过回滚记录生成反向的更新SQL并执行,完成分支事务的回滚。
开启Seata AT模式下全局分布式事务:
(1)引入相关依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
    <version>2.1.0.RELEASE</version>
</dependency>

(2)添加seata配置文件registry.conf(注册配置),该配置用于指定TC的注册中心和配置文件,默认都是file。创建file.conf,该配置用于指定TC的相关属性,是各大微服务的RM和TC之间的通信配置。
(3)注入数据源,Seata通过代理数据源的方式实现分支事务。Mybatis和JPA都需要注入io.seata.rm.datasource.DataSourceProxy,Mybatis还需要额外注入org.apache.ibatis.session.SqlSessionFactory。
(4)在业务相关的数据库中添加undo_log表,用于保存需要回滚的数据。

CREATE TABLE `undo_log` (
  			`id` bigint(20) NOT NULL AUTO_INCREMENT,
  			`branch_id` bigint(20) NOT NULL,
  			`xid` varchar(100) NOT NULL,
  			`context` varchar(128) NOT NULL,
  			`rollback_info` longblob NOT NULL,
  			`log_status` int(11) NOT NULL,
  			`log_created` datetime NOT NULL,
  			`log_modified` datetime NOT NULL,
  			PRIMARY KEY (`id`),
  			UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

(5)启动Seata-Server(TC)
(6)使用@GlobalTransactional注解开启事务。在需要执行分布式事务的入口方法上添加@GlobalTransactional注解开启全局事务。
TCC模式需要手动写代码,主要关注业务拆分,在按照业务横向扩展资源时,解决微服务间调用的一致性问题,基本思路是使用侵入业务上的补偿及事务管理器的协调来达到全局事务的一起提交或回滚。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值