1、简述
随着企业规模的扩大和业务复杂性的增加,分布式系统的应用变得越来越普遍。在这样的环境中,事务处理变得尤为重要,而本地事务和分布式事务则成为了两个不可忽视的关键概念。本文将深入探讨本地事务和分布式事务的技术实践,探讨其优势、挑战以及解决方案。
2、本地事务
2.1 事务的基本性质
数据库事务四大特性: Atomic原子性、Consistency一致性、Isolation隔离性和Durability持久性,简称就是ACID
- 持久性:当事务回滚或者提交之后,数据库会持久化数据
- 一致性:事务操作前后,数据的总量不变
- 原子性:是不可分割的最小单位,不可分割,要么同时成功要么同时失败,不可分割
- 隔离性:各个事务之间相互独立
2.2 事务的隔离级别
隔离级别从低到高分为四级:
- Read uncommitted(读未提交)
该隔离级别的事务会读到其他未提交事务的数据,此现象也称为脏读。
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
- Read committed(读已提交)
一个事务可以读取另一个已提交的事务,多次读取会造成不一样的结果,此现象称为不可重复读问题,Oracle和SQL Server的默认隔离级别。
@Transactional(isolation = Isolation.READ_COMMITTED)
- Repeatable read(可重复读取)
该隔离级别是MySql默认的隔离级别,在同一个事务里,Select的结构是事务开始时时间点的状态,因此,同样的Select操作读到的结果是一致的,但是会出现幻读现象。Mysql的InnoDb引擎可以通过next-key locks机制来避免幻读。
@Transactional(isolation = Isolation.REPEATABLE_READ)
- Serializable(串行化)
在该隔离级别下事务都是串行顺序执行的。Mysql数据库的InnoDb引擎会给读操作隐式加一把共享锁。从而避免了脏读,不可重复读和幻读的问题。
@Transactional(isolation = Isolation.SERIALIZABLE)
2.3 事务的传播行为
- Propagation.REQUIRED
如果当前存在事务,则加入该事务,如果当前不存在事务,则创建一个新的事务。 - Propagation.SUPPORTS
如果当前存在事务,则加入该事务;如果当前不存在事务,则以非事务的方式继续运行。 - Propagation.MANDATORY
如果当前存在事务,则加入该事务;如果当前不存在事务,则抛出异常。 - Propagation.REQUIRES_NEW
重新创建一个新的事务,如果当前存在事务,延缓当前的事务。 - Propagation.NOT_SUPPORTED
以非事务的方式运行,如果当前存在事务,暂停当前的事务。 - Propagation.NEVER
以非事务的方式运行,如果当前存在事务,则抛出异常。 - Propagation.NESTED
如果没有,就新建一个事务;如果有,就在当前事务中嵌套其他事务。
2.4 同一个对象内本地事务调用失败问题
解决方法:采用代理对象来调用事务方法
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
开启AspectJ动态代理,没有接口也可以创建动态代理
@EnableAspectJAutoProxy(exposeProxy = true)
通过AopContext就可以调用对象内事务方法。
WareSkuService skuService = (WareSkuService)AopContext.currentProxy();
skuService.GetSkuHasStock(null);
3、分布式事务
3.1 CAP定理
CAP原则又称CAP定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。
- 一致性(Consistency)
在分布式系统中的所有数据备份,在同一时刻是否有同样的值(等同于所有节点访问同一份最新的数据副本)
分布式实现一致性算法:
http://thesecretlivesofdata.com/raft/ - 可用性(Availability)
在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性) - 分区容错性(Partition tolerance)
大多数分布式系统都分布在多个子网格。每个子网格就叫做一个区。分区容错的意思是,区间通信可能失败。比如,一台服务器在中国,另外一台服务器在美国,这就是两个区,他们之间可能无法通信。
备注:这三个要素最多只能同时实现两点(CP、AP),不可能三者兼顾。
3.2 BASE理论
是对CAP理论的延伸,就是即使无法做到强一致性,也可以采用弱一致性,即最终一致性。
- 基本可用
指的是分布式系统出现故障时,允许损失部分可用性(如响应时间),基本可用不等价于系统不可用。
响应时间上的损失,引擎响应延迟。
网站购物高峰期,页面的降级引导。 - 软状态
指的是允许系统存在中间状态,而该中间状态不会影响到整个系统的可用性。分布式存储一般一份数据有多个副本,允许不通副本同步的延时就是软状态的体现。mysql replication的异步也是一种体现。 - 最终一致性
指的是系统中所有数据副本经过一定时间后,最终能够达到一致的状态,弱一致性和强一致性想法。最终一致性是弱一致性的特性情况。
3.3 分布式事务实现方案
- 2PC模式
数据库二阶提交,一阶预备提交,二阶提交数据,简称XA
- 柔性事务-TCC事务补偿协议
柔性事务,遵循BASE理论,实现最终一致性。
一阶段prepare行为。
二阶段commit行为。
三阶段rollback行为。
比较典型的事务:
由阿里云提供的Seata
http://seata.io/zh-cn/docs/user/quickstart.html
- 柔性事务-最大努力通知方案
不一定通知成功,但会提供可查询接口进行核对。
当前方案,可以结合MQ来实现。
案例(银行通知,商户通知,支付宝支付成功异步调用等) - 柔性事务-可靠消息+最终一致性
实现业务处理服务在业务提交之前,向MQ实时消息服务请求发送消息。实时消息只记录消息数据,而不是真真的发送。业务处理服务在业务提交之后,向实时消息服务确认发送,只有在确认收到发送指令后,才会真正的发送实时消息。
4、结论
本地事务和分布式事务都有各自的优势和挑战。在实际应用中,开发人员需要根据业务需求和系统规模的不同权衡它们。深入了解事务管理的原理和实践,以及利用现代技术手段来解决分布式事务带来的挑战,将有助于构建稳健、高性能的分布式系统。
评论区