目录
事务的基本性质
- 原子性(Atomicity):一系列的操作整体不可拆分,要么同时成功,要么同时失败
- 一致性(Consistency):数据在事务的前后,业务整体一致
- 隔离性(Isolation):事务之间相互隔离
- 持久性(Durabilily):事务一旦成功,数据一定会落盘数据库
事务的隔离级别
- READ UNCOMMITTED(读未提交):该隔离级别的事务会读到其它未提交事务的数据,此现象也称之为脏读。
- READ COMMITTED(读提交):一个事务可以读取另一个事务已提交的,多次读取会造成不一样的结果,此现象称之为不可重复读。
- REPEATABLED READ(可重复读):该隔离级别是MySQL默认的隔离级别,在同一个事务里,select的结果是事务开始时间的状态,因此,同样的select操作读到的结果会是一致的。但是,会有幻读现象。MySQL的InnoDN引擎可以通过next-key locks机制来避免幻读。
- SERIALIZABLE(序列化):该隔离级别事务都是串行顺序执行,MySQL数据库的InnoDB引擎会给读操作隐式加一把读共享锁,从而避免了脏读、不可重复读和幻读问题。
事务的传播行为
- PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务。
- PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。
- PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
- PROPAGATION_REQUIRED_NEW:创建新事务,无论当前存不存事务,都创建新事务。
- PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
- PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
- PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行,如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
本地事务
SpringBoot 事务
事务自动配置
TransactionAutoConfiguration
事务使用
- 事务的隔离级别
@Transactional(isolation = Isolation.DEFAULT)
- 事务的传播行为
@Transactional(propagation = Propagation.REQUIRED)
本地事务失效问题
现象:同一对象内事务方法互调默认失效,原因是绕过了代理对象,事务使用代理对象来控制。
解决:使用代理对象来调用事务方法。
- 引入spring-boot-starter-aop(引入aspectj)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
- 开启aspectj动态代理功能,以后所有的动态代理都是aspectj创建的(即使没有接口也可以创建动态代理),exposeProxy = true:对外暴露代理对象
@EnableAspectJAutoProxy(exposeProxy = true)
- 本类互调使用代理对象
OrderServiceImpl orderService = (OrderServiceImpl) AopContext.currentProxy()
分布式事务
CAP定理
- 一致性(Consistence):在分布式系统中所有数据备份,在同一时刻是否同样的值(等同于所有节点访问同一份最新数据副本)
- 可用性(Availlability): 在集群中一部分节点故障后,集群整理是否还能响应客户端读写请求(对数据更新具备高可用性)
- 分区容错性(Partition Tolerance):大多数分布式系统都分布在多个子网络,每个子网络就叫做一个区(Partition),区间通讯可能失败。比如一台服务器部署在中国,另一台部署在美国,这就是两个区,他们之间可能无法通讯
CAP 原则指的是,这三个要素最多只能同时实现两个,不可能三者兼顾。
BASE 理论
- 基本可用(Basically Available):基本可用是指分布式系统在出现故障时,允许损失部分可用性(例如响应时间、功能上的可用性),需注意的是,基本可用绝不等价于系统不可用
- 响应时间上的损失:正常情况下搜索引擎需要在0.5s内返回给用户查询结果,但由于出现故障(比如系统断电或者网络故障),响应时间增加到1~2s。
- 功能上的损失:购物网站购物高峰时(比如双十一),为了保护系统稳定性,部分消费者可能被引导至一个降级页面。
- 软状态(Soft State):指系统存在中间状态,而该状态不会影响系统整体可用性。分布式存储一般一份数据会有多个副本,允许不同副本同步延时就是软状态的体现。mysql replication 的异步复制也是一种体现。
- 最终一致性(Eventtual Consistence):指系统中所有数据副本经过一段时间后最终能达到一致的状态。弱一致性和强一致性相反,最终一致性是弱一致性的特殊情况。
是对 CAP 定理的延伸,思想就是即使无法做到强一致性(CAP中一致性就是强一致性) ,但可以采用适当的采取弱一致性,即最终一致性。
强一致性&弱一致性&最终一致性
- 从客户端角度,多进程并发访问时,更新过的数据在不同进程如何获取的不同策略,决定了不同的一致性,对于关系型数据库,要求更新过的数据能被后续的访问继续都能看到,这就是强一致性。如果能容忍后续的部分或者全部访问不到,则是弱一致性。若果经过一段时间后要求能访问到更新后的数据,则是最终一致性。
分布式事务解决方案
- 刚性事务:遵循ACID原则,强一致性
- 柔性事务:遵循BASE理论,最终一致性
2PC模式
数据库支持的2PC【2 phase commit 二阶提交】,又叫 XA Transactions。XA 是一个两阶段提交协议。
第一阶段:事务协调器要求涉及到事务的数据库预提交(precommit),并反映是否可以提交。
第二阶段:事务协调器要求每个事务的数据库提交数据。
其中如果有任何一个数据库否决此次提交,那么所有的数据库都会被要求回滚它们在此事务中的那部分信息。
- XA 协议比较简单,而且一旦商业数据库实现了XA协议,使用分布式事务的成本也比较低。
- XA 性能不理想,特别是在交易下单链路,往往并发量很高,XA 无法满足高并发场景。
- XA 目前在商业数据库支持理想,在mysql数据库中支持不理想,mysql的XA实现没有记录prepare阶段日志,主备切换会导致主数据库与备数据库数据不一致。
- 许多nosql也没有支持XA,这让XA的应用场景非常狭隘。
- 也有3PC,引入了超时机制(无论协调者还是参与者,在向对方发送请求后,如果长时间未收到回应则做出相应处理)
柔性事务-TCC事务补偿型方案
一阶段 prepare 行为:调用自定义的 prepare 逻辑。
二阶段 commit 行为:调用自定义的 commit 逻辑。
二阶段 rollback 行为:调用自定义的 rollback 逻辑。
所谓的 TCC 模式,是指把自定义的分支事务纳入到全局事务的管理中。
柔性事务-最大努力通知型方案
- 按规律进行通知,不保证数据一定能通知成功,但会提供可查询操作的接口进行核对。这种方案主要用在第三方系统通讯时,比如:调用微信或者支付宝支付后的支付结果。这种方案也是结合MQ进行实现,比如:通过MQ发送http请求,设置最大通知次数,达到通知次数后即不再通知。
柔性事务-可靠消息+最终一致性方案(异步确保型)
- 业务处理服务在业务事务提交前,向实时消息服务请求发送消息,实时消息服务只要记录消息数据,而不是真正发送。业务处理服务在业务事务提交后,向实时消息服务确认发送。只有在得到确认发送指令后,实时消息服务才会真正发送。
SEATA分布式事务解决方案
- TC (Transaction Coordinator) - 事务协调者:维护全局和分支事务的状态,驱动全局事务提交或回滚。
- TM (Transaction Manager) - 事务管理器:定义全局事务的范围:开始全局事务、提交或回滚全局事务。
- RM (Resource Manager) - 资源管理器:管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。