分布式事务
一个请求跨域了多个服务,如何保证多个微服务对数据库操作的一致性
可以使用分布式事务,可以确保系统中所使用的数据是一致的
使用seata来对系统进行事务管理
在seata中有三个角色,TC、TM、RM
TC(事务协调者):协调全局事务的提交和回滚
TM(事务管理器):定义全局事务范围,开启全局事务,提交或回滚全局事务
RM(资源管理器):管理分支事务,向TC注册事务、报告分支事务状态,并驱动分支事务提交或回滚
seata架构提供了四种分布式事务处理方案
XA模式:强一致性分阶段事务模式,牺牲一定可用性,无业务入侵
AT模式:最终一致的分阶段事务模式,无业务入侵,seata的默认模式
TCC模式:最终一致的分阶段事务模式,有业务入侵
SAGA模式:长事务模式,有业务入侵
CAP定理
C:一致性
在分布式系统中,所有节点中所有数据副本,在同一时刻相同
A:可用性
系统能够在一定时间内给出响应,而不是一个错误的响应提示
P:分区容错
分布式系统各个节点之间可能会因为网络故障等原因导致消息无法正常传递,要么保证一致性但牺牲可用性,要么保证可用性但牺牲一致性
BASE定理
Basically Available (基本可用):分布式系统在出现故障时,允许损失部分可用性,即保证核心可用。
**Soft State(软状态):**在一定时间内,允许出现中间状态,比如临时的不一致状态。
Eventually Consistent(最终一致性):虽然无法保证强一致性,但是在软状态结束后,最终达到数据一致。
seata分布式事务中四种模式的工作原理,AT模式可能出现的问题
XA模式,处理分布式事务是分两段提交的
RM一阶段的工作:
① 注册分支事务到TC
② 执行分支业务sql但不提交
③ 报告执行状态到TC
TC二阶段的工作:
-
TC检测各分支事务执行状态
a.如果都成功,通知所有RM提交事务
b.如果有失败,通知所有RM回滚事务
RM二阶段的工作:
- 接收TC指令,提交或回滚事务
AT模式,处理分布式事务是分两段提交的
一阶段:
- TM开启全局事务
- TM调用分支
- RM注册分支事务
- RM创建数据快照(将数据存入undo_log表)
- RM向TC报告是无状态
二阶段:
- TM提交或回滚全局事务
- TC检查分支事务状态
- RM提交或回滚事务
- 删除或恢复undo_log表中的数据
TTC模式,分为三个阶段
try阶段
会预留程序运行所必需的资源,并将该资源存入数据库中
confirm阶段
该阶段会对预存的数据进行真正的操作,当确认成功时更新数据库中数据,并将预存的数据删除
cancel阶段
如果在确认阶段发生错误,则回滚尝试阶段所做的任何修改。此时,TCC 会触发一个取消操作,用于确认所有资源已被正确释放。在此过程中,必须清除所有已经进入 TCC 状态机的状态,以确保最终一致性。
SAGA模式
一阶段:直接提交本地事务
二阶段:成功则什么都不做;失败则通过编写补偿业务来回滚
@Transaction事物的传播行为
在 Spring 中,事务的传播属性用于控制一个事务方法调用另外一个事务方法时,这两个事务方法之间事务的管理方式。当在一个事务方法中调用另外一个事务方法时(如方法 A 调用方法 B),Spring 就会根据方法 A 和方法 B 的事务传播属性来确定到底如何管理这两个方法之间的事务。
常见的事务传播属性包括:
- REQUIRED:默认值。如果当前已经存在事务,则加入该事务,否则创建新事务。
- REQUIRES_NEW:无论当前是否存在事务,都创建一个新的事务,如果存在事务则将其挂起。
- SUPPORTS:如果当前存在事务,则加入该事务,否则以非事务方式执行。
- NOT_SUPPORTED:以非事务方式执行,如果当前存在事务,则将其挂起。
- MANDATORY:必须在已有的事务中执行,否则抛出异常。
- NEVER:必须以非事务方式执行,如果当前存在事务,则抛出异常。
- NESTED:如果当前存在事务,则在嵌套事务内执行,否则与 REQUIRED 类似。嵌套事务是独立的,拥有自己的 savepoint。内部事务提交或回滚不会影响外部事务,但外部事务的提交会提交所有嵌套事务,而回滚会回滚到最近的 savepoint,并结束所有嵌套事务。
在选择事务传播属性时,需要根据实际情况进行选择,以达到在保证数据一致性和可靠性的前提下,尽可能地减少性能损耗。
@Transactional自定义回滚异常
在@Transactional注解中添加rollbackFor ,来指定出现某种异常的时候进行回滚
自定义一个异常类
在注解中添加该异常
在方法中抛出该异常
事务的隔离级别
-
读未提交
一个事务做出的修改即使没有提交,其他事务也可以看到他做出的修改,隔离级别最弱,也最不安全,可能会导致脏读
-
读已提交
一个事务只能读取到已经提交的数据,因此其他事物在再提交之前做的修改对于当前事务来说是不可见的,可能出出现重复读和幻读
-
可重复读
一个事务在执行期间再次读取同一条记录时,总能得到相同的结果,而且该条事务被锁定,其他事务不能进行操作,仍存在幻读
-
串行化
所有事物是串行执行的,当一个事务在访问数据时,其他事务不能对其进行读写操作,隔离性最高,性能同时也是最低的
事物的4大特征
原子性
一致性
隔离性
持久性
脏读
脏读是指一个事务读取到了另一个事务未提交的数据。在读未提交的隔离级别下,当一个事务修改了某条记录但还未提交时,另外一个事务就可以读取到这个未提交的数据,即读到了“脏”的数据,这样会导致数据的不一致性和错误结果。例如,如果A事务将银行账户中的余额从100元改为200元,但还未提交,此时B事务读取银行账户余额时就会读到200元,而实际上该值并未提交,因此会产生脏读问题。
因为脏读会导致数据的不一致性和错误结果,所以在实际应用中应尽量避免使用读未提交的隔离级别,而要选择更高级别的隔离级别,如读已提交、可重复读或串行化,以保证数据的正确性和完整性。
幻读
脏读是指一个事务读取到了另一个事务未提交的数据。在读未提交的隔离级别下,当一个事务修改了某条记录但还未提交时,另外一个事务就可以读取到这个未提交的数据,即读到了“脏”的数据,这样会导致数据的不一致性和错误结果。例如,如果A事务将银行账户中的余额从100元改为200元,但还未提交,此时B事务读取银行账户余额时就会读到200元,而实际上该值并未提交,因此会产生脏读问题。
因为脏读会导致数据的不一致性和错误结果,所以在实际应用中应尽量避免使用读未提交的隔离级别,而要选择更高级别的隔离级别,如读已提交、可重复读或串行化,以保证数据的正确性和完整性。