Seata
2024-03-25 13:51:34 1 举报
AI智能生成
Seata一个不错的学习笔记:分布式事务、二阶段、AT模式、TCC模式、SAGA模式,Seata的rpc设计、Seata的TC设计
作者其他创作
大纲/内容
Seata
原子性
一致性
隔离性
持久性
事务的四种特性
以xa_开头:- xa_open() xa_close():建立/关闭与资源管理器事务的链接- xa_start() xa_end() : 开始/结束一个本地事务- xa_prepare() xa_commit() xa_rollback() : 预提交、提交、回滚一个本地事务- xa_recover() 回滚一个已进行预提交的事务以ax_开头:- ax_reg() ax_unreg() 允许一个资源管理器在事务协调器中动态注册/撤销注册
XA两阶段函数
第一阶段:1. 事务协调器通知参与该事务的所有资源管理器开始准备事务2. 资源管理器接收到消息之后开始准备(写事务日志、执行事务,但是不提交),then将就绪的消息返回给事务协调器。此时大部分事务已经完成,第二阶段耗时很短第二阶段1. 事务协调器接收到各个资源管理器回复消息之后,基于投票进行决策---提交/取消。如果有任意一个资源管理器回复失败,则发送回滚的命令,否则发送提交的命令2. 各个资源管理器在接收事务协调器的提交/回滚的请求之后,执行,并将执行结果返回给事务协调器
两阶段提交协议的执行过程
同步阻塞问题
事务协调器发生故障
单点故障
第二阶段处理中,如果发生了commit的异常、那么部分接到commit请求的资源管理器就会执行commit请求,但是其他的资源管理器不会执行,所以此阶段会造成事务不一致问题
数据不一致
如果事务协调器发起commit后宕机、并且对应的资源管理器也宕机了那么此时状态就没有办法回溯了
状态不稳定
两阶段提交协议的缺点
XA两阶段提交协议
CAP理论
基本可用是对CAP中的A的一个妥协分布式系统出现不可预知的故障时,允许损失部分可用性比如高并发的时候的降级等
基本可用
允许系统中各个节点的数据处于中间状态
软状态
软状态的终态,各个节点的数据副本的最终一致性
最终一致性
BASE理论
尽早的对所操作的资源“加锁”,如果事务可以提交,则完成对预留资源的操作;如果事务不可以提交,则对预留的资源进行回滚
核心思想
try:完成业务准备工作confirm:操作阶段完成业务提交cancel:操作阶段完成业务回滚
TCC柔性事务
简单来讲就是将分布式事务转换为两个本地事务然后依靠下游的重试机制达到最终一致性
缺点:对应用侵入性很强、应用需要进行大量的业务改造,成本较高
基于消息的最终一致性
概念
为Seata主推的模式,对于业务无侵入,实现了业务与事务分离只需要新增一个事务注解@GlobalTransactional
AT模式
开发者需要根据自己的具体的业务背景去实现,try、confirm、cancel的方法
TCC模式
补偿协议- 如果所有的正向操作均执行成功,则分布式事务提交如果任何一个正向操作执行失败,则分布式事务会退回去执行前面参与者的逆向回滚操作,回滚已提交的参与者,使分布式事务会到初始状态缺点:在一阶段已经提交了本地数据库的事务,且没有进行“预留”动作,所以不能保证隔离性,不容易进行并发控制。适用场景十分有限。
Saga模式
XA模式
Seata支持4种事务模式:AT、TCC、Saga、XA
Seata原理
在数据源代理DataSourceProxy拦截业务SQL之后,会生成包含before-image和after-image信息的事务日志,并保存在事务日志标 (表名:undo_log、事务日志在Seata中称为undoLog)核心重点字段:rollback_info字段,记录了回滚的数据信息,内部有前置镜像和后置镜像。
org.apache.seata.rm.datasource.sql.struct.TableRecords表元数据、表名称、行集合
org.apache.seata.sqlparser.struct.TableMeta表名称、列元素映射、索引元数据映射
org.apache.seata.sqlparser.struct.ColumnMeta列名、数据类型、是否为空等.......
org.apache.seata.sqlparser.struct.IndexMeta索引名称、索引类型、是否唯一索引、包含的列
afterImage中的字段数据
1. 定义一个 缓存 大小100kb 失效时间900s【基于咖啡因 Caffeine】
2. org.apache.seata.rm.datasource.sql.struct.cache.AbstractTableMetaCache#getTableMeta方法获取元数据,如果cache中没有,则从数据库获取
org.apache.seata.rm.datasource.sql.struct.cache.MysqlTableMetaCache#resultSetMetaToSchema在数据表变动不是很频繁的情况下,seata遵循读多写少用缓存的原则,并通过定时任务的方式来保持拿到的数据表元数据是最新的。
元数据加载
数据类型定义Classjava.sql.Types
org.apache.seata.rm.datasource.undo.AbstractUndoLogManager#flushUndoLogs保存事务日志方法
org.apache.seata.rm.datasource.undo.AbstractUndoLogManager#undo二阶段回滚方法
org.apache.seata.rm.datasource.undo.AbstractUndoLogManager#deleteUndoLog二阶段回滚处理的删除事务日志方法
org.apache.seata.rm.datasource.undo.AbstractUndoLogManager#batchDeleteUndoLog二阶段提交处理的批量删除事务日志方法
事务日志的处理逻辑一般都在UndoLogManager中
事务日志表undo_log
Seata对java.sql中的DataSource、Connection、Statement、PreparedStatement四个接口进行了包装DataSourceProxy、ConnectionProxy、StatementProxy、PreparedStatementProxy
数据源代理类
org.apache.seata.core.model.ResourceManager
ResourceManager
org.apache.seata.core.model.ResourceManagerInbound主要是对内操作,接收TC发来的请求【提交分支事务、回滚分支事务】
ResourceManagerInbound
主要是对外的操作,发送请求到TC【注册分支事务、上报分支状态、查询全局锁】
ResourceManagerOutbound
1. 获取分支事务类型2. 获取资源管理器3. 注册资源,通过RPC客户端注册资源,将当前的资源组ID和资源ID发给TC
资源注册
资源管理器
org.apache.seata.rm.datasource.DataSourceProxy#getConnection()通过目标数据源创建连接代理
创建数据库代理
本地事务提交
数据库连接代理
1. Statement用于执行静态的SQL语句,需要实现准备2. PreparedStatement支持动态参数,比如 ?3. PreparedStatement执行SQL,SQL会先被数据库解析和编译,然后放入命令缓冲区。执行同一个PreparedStatement对象,都会再次解析,但是不会再次编译,因为缓冲区有预编译的命令,并且可以重用4. PreparedStatement减少编译次数,提高数据库性能5. PreparedStatement有更好的安全性
Statement和PreparedStatement的区别
PreparedStatement相关关系图
1.SQL识别器 SQL识别器是通过Druid SQL识别器工厂创建的org.apache.seata.sqlparser.druid.DruidSQLRecognizerFactoryImpl
a、生成前镜像org.apache.seata.rm.datasource.exec.UpdateExecutor#beforeImage
b、执行原始SQL语句
c、生成后镜像org.apache.seata.rm.datasource.exec.BaseInsertExecutor#afterImage
d、准备事务日志org.apache.seata.rm.datasource.exec.BaseTransactionalExecutor#prepareUndoLog
2.SQL执行器org.apache.seata.rm.datasource.exec.BaseTransactionalExecutor#execute
执行模板类 ExcuteTemplete的execute方法org.apache.seata.rm.datasource.exec.ExecuteTemplate如果sql语句不在分布式事务中,并且也没有Seata全局锁的要求,则不需要将其纳入Seata框架下进行处理,用原始的Statement方法处理即可;如果这个SQL语句在分布式事务中,则将其纳入Seata框架进行处理,并根据不同SQL语句类型选用不同的执行器来执行
StatementProxy & PreparedStatementProxy
Seata数据源代理
源码分析
通过数据源代理生成SQL识别器和SQL执行器,然后执行1. 开启一个数据库本地事务2. 查询前镜像3. 执行SQL4. 查询后镜像5. 生成事务日志和事务锁数据6. 注册分支事务 - 如果注册成功,则分支提交成功,执行后续 - 如果发生全局锁冲突,则回滚本地事务,在休眠一段时间之后,重新执行1-67. 提交本地事务8. 向TC汇报分支状态
Seata AT模式一阶段
第一阶段
Seata AT模式二阶段 -- 提交
提交
脏写判断:1. 如果当前值和后镜像相同,则无“脏写”,不回滚2. 如果当前值和后镜像不同,但是和前镜像相同,则无“脏写”,值已经是我们预期3. 如果当前值和前后镜像都不相同,则发生了“脏写”,会抛出异常
注意⚠️:由于TC在一阶段已经对AT模式分支事务生成的行锁数据进行了“加锁”,所以正常情况并不会出现脏写的情况。出现“脏写”通常是有人绕过了Seata对数据进行了修改,比如通过SQL工具直接修改数据,这并不服务Seata AT的规则,需要人工排除
Seata AT模式二阶段 -- 回滚
回滚
第二阶段
二阶段流程图
AT模式两阶段提交
1.TM【事务管理器】端使用`@GlobalTransaction`进行全局事务开启、提交、回滚2.TM【事务管理器】开始RPC调用远程服务3.RM【资源管理器】端`seata-client`通过扩展`DataSourceProxy`,实现自动生成`UNDO_LOG`与`TC`【事务协调器】上报4.TM【事务管理器】告知TC【事务协调器】提交/回滚全局事务5.TC【事务协调器】通知RM【事务管理器】各自执行`commit/rollback`操作,同时清除`undo_log`
背景举例
AT模式处理步骤
Seata AT模式
TCC 模式是 Seata 支持的一种由业务方细粒度控制的侵入式分布式事务解决方案,是继 AT 模式后第二种支持的事务模式,最早由蚂蚁金服贡献。其分布式事务模型直接作用于服务层,不依赖底层数据库,可以灵活选择业务资源的锁定粒度,减少资源锁持有时间,可扩展性好,可以说是为独立部署的 SOA 服务而设计的。
1. AT模式AT模式依赖关系型数据库的本地事务能力- 一阶段prepare:seata框架自动完成(在一个本地事务内完成)- 二阶段commit:seata框架自动清理事务日志- 二阶段rollback:seara框架自动完成事务的回滚2. TCC模式TCC模式不强依赖本地事务的能力- 一阶段prepare:调用自定义的prepare逻辑- 二阶段commit:调用自定义的commit逻辑- 二阶段rollback:调用自定义的rollback逻辑两种模式的差别:在AT模式下seata把每一个数据库当作一个资源在TCC模式下,Seata把每组TCC服务接口当作一个资源
优势TCC 完全不依赖底层数据库,能够实现跨数据库、跨应用资源管理,可以提供给业务方更细粒度的控制。缺点TCC 是一种侵入式的分布式事务解决方案,需要业务系统自行实现 Try,Confirm,Cancel 三个操作,对业务系统有着非常大的入侵性,设计相对复杂。适用场景TCC 模式是高性能分布式事务解决方案,适用于核心系统等对性能有很高要求的场景。
概述
使用
Seata TCC模式
Seata通过Netty实现作为RPC的底层通信
网络通信
事务消息信息分为3大类:1. TM主动向TC发起2. RM主动向TC发起3. TC主动向RM发起
事务消息信息
Seata RPC设计
Seata Server
Seata 事务协调器
0 条评论
下一页