分布式事务 2PC, 3PC, TCC, Saga
数据库事务 在讲述分布式事务的概念之前,我们先来回顾下事务相关的一些概念。 事务的基本概念: 就是一个程序执行单元,里面的操作要么全部执行成功,要么全部执行失败,不允许只成功一半另外一半执行失败的事情发生。例如一段事务代码做了两次数据库更新操作,那么这两次数据库操作要么全部执行成功,要么全部回滚。 事务的基本特性: 我们知道事务有4个非常重要的特性,即我们常说的 (ACID) 。 Atomicity (原子性) 事务是一个不可分割的整体,所有操作要么全做,要么全不做。一旦其中某个操作出错,整个事务回滚到开始前的状态,已执行的操作全部撤销。比如 A 向 B 转账,扣款和入账这两步必须同时成功或同时失败,不能只扣了 A 的钱而 B 没收到。 Consistency (一致性) 是说事务执行前后,数据必须满足预定义的约束和规则,从一个合法状态转换到另一个合法状态。比如 A 向 B 转账,无论事务是否成功,A 和 B 的账户总金额必须保持不变——这个"总额守恒"就是一致性约束。注意:A 扣了钱 B 没收到,描述的是原子性被破坏;一致性关注的是业务规则(约束)是否始终成立。 Isolation (隔离性) 多个并发事务之间相互隔离,不能互相干扰。并发事务操作同一份数据时,可能出现三类读异常: 脏读:事务 A 读取了事务 B 尚未提交的数据,若 B 随后回滚,A 读到的就是无效数据。解决方法:隔离级别提升到"读已提交"。 不可重复读:事务 A 在同一事务内两次读取同一行,期间事务 B 修改并提交了该行,导致两次结果不同。解决方法:隔离级别提升到"可重复读"。 幻读:事务 A 在同一事务内两次执行相同的范围查询,期间事务 B 插入或删除了符合条件的行并提交,导致两次结果集的行数不同——凭空多出或少了几行,如同"幻象"。注意:幻读的前提是 A 本身处于事务中,且处于"可重复读"隔离级别(该级别能保证已有行不变,但挡不住新插入的行)。解决方法:隔离级别提升到"串行化",或使用间隙锁(Gap Lock)。 四个隔离级别(读未提交、读已提交、可重复读、串行化)依次能解决脏读、不可重复读、幻读,但隔离级别越高并发性能越低。 Durability (持久性) 事务一旦提交,其对数据库的修改就会被永久保存,即使系统崩溃或重启也不会丢失。数据库通过 WAL(Write-Ahead Log,预写日志)等机制来保证持久性。 关于数据库事务的基本概念大家可以去网上搜一下,这里只是给大家回顾下事务的基本概念及特性,诸如事务并发问题、事务隔离级别等大家如有遗忘可以去回顾下 (tips: 面试经常会问到的问题哦) 。 分布式事务 以上内容我们回顾了下事务的基本概念,那么分布式事务又是个什么概念呢?它与数据库事务之间又有什么区别呢? 其实分布式事务从实质上看与数据库事务的概念是一致的,既然是事务也就需要满足事务的基本特性 (ACID) ,只是分布式事务相对于本地事务而言其表现形式有很大的不同。举个例子,在一个JVM进程中如果需要同时操作数据库的多条记录,而这些操作需要在一个事务中,那么我们可以通过数据库提供的事务机制 (一般是数据库锁) 来实现。 ...