2020年是比较难过的一年,IT行业也不例外。平时多学习学习,保持核心竞争力。我始终相信:只要方向对了,努力坚持,该来的始终会来的。
今天来聊聊面试的必聊话题:事务。先抛出几个问题:
- 什么是事务。
- spring是怎么实现事务的。
- 什么是分布式事务。
- 分布式事务的实现方式。
什么是事务?
事务是指一个业务逻辑中的一系列操作作为一个整体,这些操作要么全部成功,要么全部失败回滚。
事务四大特性:原子性,隔离性,持久性,一致性。
原子性是基础,隔离性,持久性是手段,一致性是目的。一系列操作作为一个原子,不可再分割,通过事务间隔离,互不影响,执行结果持久化,达到最终的目的数据一致性。
spring事务实现
在说spring事务实现前,看下JDBC的事务是怎么实现的。
核心是设置Connection手动提交,根据业务逻辑执行情况提交或回滚操作。
使用过XML配置spring工程的都知道,需在XML配置事务管理器bean,事务通知和代理管理配置。
如:Hibernate,事务管理器为HibernateTransactionManager
还是声明式事务
@Transactional
public void transactionBusiness() {
//业务逻辑
}
其原理都是底层建立在 AOP 的基础之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。
通过TransactionInterceptor 来定义相关的事务规则,其中一个核心属性transactionManager,用来指定一个事务管理器,并将具体事务相关的操作委托给它。
在创建事务时createTransactionIfNecessary()调用tm.getTransaction(txAttr);获取并开启事务,设置autoCommit为false
分布式事务
分布式事务是指业务的一系列操作分布在不同的应用或不同的管理资源的原子性操作。既然是事务,也是要满足传统事务的四大特性。但由于分布在不同的应用,接口调用必然会存在着各种各样的问题,如网络分区。
分布式系统的两大定理:
CAP
CAP原则又称CAP定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容忍性(Partition tolerance)。CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。
· 一致性:在分布式系统中的所有数据备份,在同一时刻是否同样的值。
· 可用性:在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。
· 分区容忍性:以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。
BASE理论
BASE理论是对CAP中的一致性和可用性进行一个权衡的结果,理论的核心思想就是:我们无法做到强一致,但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性。
· Basically Available(基本可用)
· Soft state(软状态)
Eventually consistent(最终一致性)
分布式事务解决方案:
类似于PlatformTransactionManager事务管理器,分布式事务引入了第三者充当管理器,统一调度各事务分支提交或回滚。
两阶段提交(2PC)
阶段一
a) 协调者向所有参与者发送事务内容,询问是否可以提交事务,并等待答复。
b) 各参与者执行事务操作,将 undo 和 redo 信息记入事务日志中(但不提交事务)。
c) 如参与者执行成功,给协调者反馈 yes,否则反馈 no。
阶段二
如果协调者收到了参与者的失败消息或者超时,直接给每个参与者发送回滚(rollback)消息;否则,发送提交(commit)消息。两种情况处理如下:
情况1:当所有参与者均反馈 yes,提交事务
a) 协调者向所有参与者发出正式提交事务的请求(即 commit 请求)。
b) 参与者执行 commit 请求,并释放整个事务期间占用的资源。
c) 各参与者向协调者反馈 ack(应答)完成的消息。
d) 协调者收到所有参与者反馈的 ack 消息后,即完成事务提交。
情况2:当有一个参与者反馈 no,回滚事务
a) 协调者向所有参与者发出回滚请求(即 rollback 请求)。
b) 参与者使用阶段 1 中的 undo 信息执行回滚操作,并释放整个事务期间占用的资源。
c) 各参与者向协调者反馈 ack 完成的消息。
d) 协调者收到所有参与者反馈的 ack 消息后,即完成事务。
三阶段提交(3PC)
三阶段提交是在二阶段提交上的改进版本,3PC最关键要解决的就是协调者和参与者同时挂掉的问题,所以3PC把2PC的准备阶段再次一分为二,这样三阶段提交。
无论2PC还是3PC,都依赖于数据库的XA协议,且事务期间都一直占用着资源,高并发下性能有所影响。
补偿事务(TCC)
TCC 是服务化的二阶段编程模型,采用的补偿机制
处理流程:
a) Try 阶段主要是对业务系统做检测及资源预留。
这个阶段主要完成:
完成所有业务检查( 一致性 ) 。
预留必须业务资源( 准隔离性 ) 。
Try 尝试执行业务。
b) Confirm 阶段主要是对业务系统做确认提交。
Try阶段执行成功并开始执行 Confirm阶段时,默认 Confirm阶段是不会出错的。即:只要Try成功,Confirm一定成功。
c) Cancel 阶段主要是在业务执行错误,需要回滚的状态下执行的业务取消,预留资源释放。
MQ事务消息(最终一致性)
基于消息中间件的支持事务特性,如:rocketMQ。
处理流程:
- 消费者向MQ发送half消息。
- MQ Server将消息持久化后,向发送方ack确认消息发送成功。
- 消费者开始执行事务逻辑。
- 消费者根据本地事务执行结果向MQ Server提交二次确认或者回滚。
- MQ Server收到commit状态则将half消息标记可投递状态。
- 服务提供者收到该消息,执行本地业务逻辑。返回处理结果。
终极大招:阿里的seata。
Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。
最大特点是:各分支事务记录业务数据和回滚日记在本地事务后立即提交,释放本地资源。追求对代码无侵入。
个人看好seata,后面有时间学习一下再写seata各种模式的具体实现。
以上是个人对事务的一些理解,不对的地方欢迎留言指出,不胜感谢。