什么是本地事务
ACID
- 原子性:是指一个事务是一个不可分割的工作单位,其中的操作要么都做,要么都不做;如果事务中一个 SQL 语句执行失败,则已执行的语句也必须回滚,数据库退回到事务前的状态。(
undo log
回滚日志,每条 SQL 生成相反的操作) - 隔离性:一个事务的操作不影响另一个事务(写写锁机制保证,写读 MVCC 保证)
- 持久性:是指事务一旦提交,它对数据库的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。(
redo log
重做日志,可以想像redo log
就是粉板,先记到粉板,闲的时候再写到账本,crash recovery) - 一致性:事务要保证数据库整体数据的完整性和业务数据的一致性,事务成功提交整体数据修改,事务错误则回滚到数据回到原来的状态(只有上面 3 个特性符合才能保证一致性)
分布式事务解决什么问题
CAP
- C 一致性
- A 可用性
- P 分区容错性
不能同时满足,只能 CP(强一致性)、AP(确保可用性,不能保证一致性)
BASE
- 基本可用:允许损失部分可用性
- 软状态:允许数据存在中间状态
- 最终一致性:系统所有副本,经过一段时间同步,达到最终一致的状态
分布式事务的解决方案
可靠事件队列
原理
将最容易出错的业务放到本地事务执行,后续其他业务只需成功不许失败(如果一直失败,人工介入)
比如转账(账户 A、账户 B 在不同的服务器上),账户 A 扣 30,账户 B 加 30
- 账户 A 扣除 30,并保存到本地消息表状态为进行中,放到一个事务中。如果失败就会滚,后续不会执行。
- 消息服务会定时轮询消息表,状态为进行中的消息发送给账户 B。
- 账户 B 收到消息处理加 30 操作,如果处理失败循环直至成功,处理成功更新消息表已完成。
- 第 3 步如果由于网络原因无法更新消息表,消息服务会重发消息给账户 B,此时需要保证消息幂等性。
优点
缺点
- 隔离性差
TCC 事务
原理
Try-Confirm-Cancel
- Try:尝试执行阶段,完成所有业务可执行性的检查(保障一致性),并且预留好全部需用到的业务资源(保障隔离性)。
- Confirm:确认执行阶段,不进行任何业务检查,直接使用 Try 阶段准备的资源来完成业务处理。Confirm 阶段可能会重复执行,因此本阶段所执行的操作需要具备幂等性。
- Cancel:取消执行阶段,释放 Try 阶段预留的业务资源。Cancel 阶段可能会重复执行,也需要满足幂等性。
比如转账(账户 A、账户 B 在不同的服务器上),账户 A 扣 30,账户 B 加 30
- try 阶段:账户 A 预留 30 块钱,处于冻结状态。可行进入 conform 阶段,不可行进入 cancel 阶段。账户 B 检查业务可行性不需要预留资源
- confirm 阶段:如果第 1 步都可行,账户 A 扣减预留的 30,账户 B 加 30
- 如果第 2 步全部完成,事务正常结束。如果任何一方出现异常,重复执行 confirm 操作,尽最大努力交付
- 如果第 1 步任何一方反馈不行,进入 cancel 阶段。账户 A 释放冻结的 30 块钱,账户 B 取消业务
- 如果第 4 步全部完成,事务正常回滚。如果有任何一方异常,重复执行 cancel 操作,尽最大努力交付
优点
- 性能好
- 有较强的隔离性
缺点
- 业务侵入性强
- 需要为资源设计冻结状态和撤销冻结的操作
SAGA 事务
原理
比如转账(账户 A、账户 B 在不同的服务器上),账户 A 扣 30(补偿操作:账户 A 加 30 元),账户 B 加 30(补偿操作:账户 B 扣 30 元)
假如账户 B 加 30 失败,会执行补偿操作,补偿操作需要有幂等性,补偿操作失败会不断重试直到成功(理论上不允许失败)
优点
- 业务侵入性小
缺点
- 无法保证隔离性(账户 B 加 30 块钱成功,账户 A 执行失败,此时另外一个事务从账户 B 扣走 30 元,执行补偿操作账户 B 无法扣 30 块钱)。可以用锁保证串行,或者先冻结资金持有这部分资源
讨论区
登录评论