分布式事务
什么是事务
事务是在一系列操作过程中,所有的操作要么全部成功,要么全部失败,如果某一个操作失败,则所有的操作都回滚到这一系列操作执行之前的状态。
事务的特性(ACID)
- A: Atomic, 原子性,所有操作作为原子执行,要么全部成功,要么全部失败
- C: Consistent, 一致性,事务开始和结束后数据的完整性不能被破坏,例如A增加了100元,则B必定减少了100元
- I: Isolated, 隔离性,不同事务之间互不影响,每个事务做出的修改必须与其他事务隔离。
- D: Durability, 持久性,事务完成后对数据的修改是永久性的,即使系统故障也不会丢失。
事务的隔离级别
多个并发执行的事务在执行过程中涉及到同一数据的修改时,可能会导致数据的不一致性。
脏读
一个事务读取了另一个事务未提交的数据。脏读数据就是未提交的数据,当一个事务对一条数据进行修改后,但事务还没有完成并提交修改的时候,另一个事务读取了该数据,并在这个数据的基础上做了进一步处理,就形成了脏读。
例如:账号上本来有100元,小明买一瓶水减去5元,但是还没有提交事务,此时小红看到账户有95元,也买了一瓶水也减去5元,没有提交事务,小明又给小红也买了一瓶水,所以又减去5元,但是此时小明以为账号中有95元,减去5元后应该是90元,所以提交了事务修改为90元,小红此时也提交事务,将账号中的数据修改为90元。最后他们用10元买了3瓶水,出现了错误。
不可重复读
一个事务过程中多次对同一数据进行读取,但是读取到的数据不一致。
例如:小明去超市买东西买东西前看到账号有100元,所以打算买100元的东西,在拿取100元物品过程中,小明之前设定好的向希望小学捐款的自动捐,向希望小学自动捐款50元,然后小明选完100元的物品去结账时又看了一下账号里只有50元了。
幻读
一个事务过程中多次执行同一查询,但是读取的结果不一致。
例如:班主任对班级中所有完成作业的同学发放一枚小红花,发放前统计了下完成作业的同学一共有20人,发放过程中,小明也完成了作业,班主任发放完成后,检查是否给所有完成作业的同学都发放了时,统计发现一共有21名同学完成,但是只发放了20枚,前后不一致,以为出现了幻觉。
事务隔离级别
级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交 | ✔ | ✔ | ✔ |
读提交 | ✖ | ✔ | ✔ |
可重复读 | ✖ | ✖ | ✔ |
串行化 | ✖ | ✖ | ✖ |
分布式事务
随着业务的拓宽,系统发杂度的提升,以及对系统可靠性的要求,慢慢的原本的单体应用会变成分布式的系统。而对于事务也要适应分布式的系统成为分布式事务。
CAP 理论
CAP 是Consistency, Availability, Partition tolerance 的缩写,分别表示一致性、可用性和分区容错性。
C:一致性:所有节点访问同一份最新的数据副本。也就是任一节点访问到的数据都必须是一样的。
A:可用性:每次请求都能获取到成功的结果,不会出现响应超时或者响应错误。
P:分区容错性:通常分布式系统的各个节点部署在不同的子网,这就是网络分区,不可避免的会出现网络问题而导致节点之间通信异常,此时任可以对外提供服务。
在所有的分布式事务场景中是不会同时具备CAP三个特性的,因为在具备了P的前提下C和A是不能共存的。例如主从架构的数据库服务,当主数据库写入数据后,从数据库需要从主数据库同步数据。
如果要保证数据一致性,则在组从数据库进行数据同步时,就必须将从数据库锁定,防止数据出现错误,同步完成后,再释放锁。
要想保证数据可用性,就必须从数据在任何时候都能获取到数据,不能响应超时或者响应错误,此时就不能锁数据库,但数据一致性就不能满足。
当所有数据都放到一个节点上,那就不需要把数据同步到其他节点,就满足一致性,同时只有一个节点数据就可以在任何时间得到响应,这也满足了可用性,但是它没有分区,不能保证节点挂掉后仍可提供服务,即不能满足分区容错性。
而构建分布式系统,从最初的需求上讲就是因为单节点系统的性能不够强大,所以才有了分布式系统。所以分区容错性就是我们不可或缺的。所以只需要考虑一致性和可用性就可以了。
选择CP还是AP
- AP :可用性 + 分区容错性
舍弃数据一致性,保证数据可用性。这个一般就是用户可以接受在一段时间内数据不是最新的,例如商品管理,当上架一款产品时,我们并不需要在我们点击上架后就必须直接能看到这个商品,我们可以接受当天,或者几分钟几小时后能看到这个商品。
- CP :一致性 + 分区容错性
舍弃可用性,保证数据一致性。这个一般是在对数据准确性要求很高的场景,哪怕这个耗时较长,或者直接失败,但是可以回滚到执行之前的状态。例如银行转账,用户在跨行转账时,必须得到双方银行都执行成功才结束事务。
BASE 理论
BASE 是Basically Avaiable、Soft-state、Eventual Consistency 的缩写,分别表示基本可用性、软状态和最终一致性。
BA :基本可用性,系统能够基本运行,允许损失一部分可用性,一直提供服务。
S :软状态,允许系统中的数据存在中间状态(CAP 中的数据一致性)认为该中间状态不会影响系统的整体可用性,也就是允许各个节点间的数据同步存在延时。
E :最终一致性,系统中所有数据副本在经过一段时间后最终数据是一致的,即保证最终数据是一样的,不需要实时一致性。
BASE 理论可以认为是 AP 的延申,不要求实时的一致性,但保证最终的一致性。例如当上架一款产品时,虽然并不是每个地区都可以直接查询到这款产品,但是可以部分地区的用户可以查询并购买到这款产品,而且最终所有地区的用户都是可以购买到这款产品,只是有的早有的晚,但最终一定可以直接查询到这款产品。
2PC 两段提交
2PC 即两段提交协议,是将整个事务流程分为两个阶段,准备阶段和提交阶段,2指两个阶段,P指准备阶段,C指提交阶段。
Mysql支持两端提交协议
准备阶段:事务管理器给每个参与者发送Prepare小心,每个数据库参与者在本地执行事务,并写本地的Undo/Redo日志,此时事务没有提交
提交阶段:如果事务管理器收到了参与者的执行失败或者超时消息时,直接给每个参与者发送回滚(Rollback)消息,否则发送提交(Commit)消息;参与者根据事务管理器的指令执行提交或者回滚操作,并释放锁。
3PC 三段提交
3PC 即三段提交协议,是2PC的升级版,是将事务分为三个阶段,CanCommit,Prepare,doCommit.
CanCommit:协调者给每个参与者发送CanCommit消息,询问是否可以执行是我提交操作,并等待各参与者的回复。各参与这反馈是否可以顺利执行。
PreCommit:协调者根据各参与者的反馈消息,执行事务预提交,或者中断事务。
DoCommit:如果各个参与者都可以进行预提交,协调者给各参与者发送DoCommit消息,各参与者收到请求后各种执行事务提交操作,并向协调者发送Ack消息,协调者收到各参与者的Ack消息后,完成事务,释放锁。
TTC 补偿事务
TTC是Try、Confirm、Cancel三个词语的缩写,TTC要求每个分支事务实现三个操作。预处理Try操作做业务检查及资源预留,确认Confirm操作业务,取消Cancel回滚操作。首先TM发起所有分支事务的Try操作,如果所有分支的Try操作全部成功,TM发起所有分支的Confirm操作,只要有任何一个分支try操作执行失败,TM就会向所有分支发起Cancel操作,回滚事务。
Try:做业务检查及资源预留
Confirm:确认提交阶段,Try阶段所有分支事务都执行成功,开始执行Confirm,正常情况下认为Confirm阶段是不会出错的,即只要try成功,confirm也会成功。如果Confirm阶段真的出错了,需要重试或者人工处理
Cancel:回滚,在Try阶段只要有一个分支事务执行失败,协调者发起Cancel操作,回滚事务,释放锁,同时正常情况下认为Cancel阶段也是不会出错的,如果出错了,需要重试或者人工处理。
TM:事务管理器,记录所有分支事务的状态,如果发现有分支事务执行失败,就发起Cancel操作,回滚事务,释放锁。