在单体架构中,我们使用关系型数据库的ACID特性,可以实现事务机制,但在微服务架构中,一次业务操作可能跨越多个服务,需要操作多个数据库,此时一个服务失败只有失败的业务会回滚,其他服务却成功了,导致数据不一致。
四种事务模式
AT
AT是一种保证最终一致性的两阶段提交模式,克服了XA模式长时间锁定资源的缺点。
第一阶段(本地提交):
- 拦截业务SQL、提取表名、条件。
- 查询并保存更新前的数据快照。
- 执行业务SQL。
- 查询并保存更新后的数据。
- 将执行SQL前后数据快照和SQL信息写入UNDO_LOG表。
- 向TC申请全局锁。
- 提交本地数据库事务,释放本地锁。
第二阶段:
- 成功:TC通知各RM异步删除undo_log,释放全局锁。
- 失败:TC通知RM回滚,RM先检查当前数据是否等于写后快照(防脏写),如果相等则根据写前快照生成反向SQL执行补偿,最后删除undo_log,释放全局锁。
优点: - 代码侵入性低:只需要加一个注解(如
@GlobalTransactional)。 - 性能好:一阶段就提交并释放了本地锁。
缺点: - 依赖关系型数据库:需要支持SQL。
- 全局锁竞争:高并发写同一行会导致性能下降。
- 脏写问题:如果有非Seata代理的业务在事务期间执行了写操作,回滚会失败。
TCC
Saga
XA(2PC)
XA是强一致性的两阶段提交方案。
第一阶段(准备):
事务协调者向所有数据源发送准备请求,各数据库执行业务SQL,但不提交事务,仍然持有数据库本地锁。
第二阶段(提交/回滚):
- 如果所有数据库操作都成功,事务协调者发送提交指令,所有数据库都进行提交并释放锁。
- 只要有一个数据库失败或超时,事务协调者发送回滚指令,所有数据库回滚并释放锁。
优点: - 无侵入:常用数据库都支持
- 强一致性:
缺点: - 性能极差:整个事务期间数据库都被锁定。
实现
Seata
见快速开始
核心架构
- 事务协调者TC (Transaction Coordinator):
- Seata的服务端,负责维护全局事务和分支事务的状态,驱动全局事务的提交或回滚。
- 事务管理器TM (Transaction Manager):
- 嵌入在发起全局事务的业务代码中(如带@GlobalTransactional注解的方法)
- 负责开启全局事务,提交或回滚事务。
- 资源管理器RM (Resource Manager):
- 管理分支事务处理的资源,负责向TC注册分支事务、报告分支状态,并接收TC指令执行分支提交或回滚。