JAVA:本地事务与分布式事务的技术指南

admin
7
2025-07-25

1、简述

随着企业规模的扩大和业务复杂性的增加,分布式系统的应用变得越来越普遍。在这样的环境中,事务处理变得尤为重要,而本地事务和分布式事务则成为了两个不可忽视的关键概念。本文将深入探讨本地事务和分布式事务的技术实践,探讨其优势、挑战以及解决方案。

image-1s7r.png


2、本地事务

2.1 事务的基本性质

数据库事务四大特性: Atomic原子性、Consistency一致性、Isolation隔离性和Durability持久性,简称就是ACID

🔹 持久性:当事务回滚或者提交之后,数据库会持久化数据

🔹 一致性:事务操作前后,数据的总量不变

🔹 原子性:是不可分割的最小单位,不可分割,要么同时成功要么同时失败,不可分割

🔹 隔离性:各个事务之间相互独立

2.2 事务的隔离级别

隔离级别从低到高分为四级:

image-4ynl.png

🔹 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

image-zbol.png

🔹 柔性事务-TCC事务补偿协议
柔性事务,遵循BASE理论,实现最终一致性。
一阶段prepare行为。
二阶段commit行为。
三阶段rollback行为。
比较典型的事务:
由阿里云提供的Seata
http://seata.io/zh-cn/docs/user/quickstart.html

image-6u2m.png

🔹 柔性事务-最大努力通知方案
不一定通知成功,但会提供可查询接口进行核对。
当前方案,可以结合MQ来实现。
案例(银行通知,商户通知,支付宝支付成功异步调用等)

🔹 柔性事务-可靠消息+最终一致性
实现业务处理服务在业务提交之前,向MQ实时消息服务请求发送消息。实时消息只记录消息数据,而不是真真的发送。业务处理服务在业务提交之后,向实时消息服务确认发送,只有在确认收到发送指令后,才会真正的发送实时消息。


4、总结

本地事务和分布式事务都有各自的优势和挑战。在实际应用中,开发人员需要根据业务需求和系统规模的不同权衡它们。深入了解事务管理的原理和实践,以及利用现代技术手段来解决分布式事务带来的挑战,将有助于构建稳健、高性能的分布式系统。

动物装饰