在一个大数据系统内部分布式事务无处不在,但凡一个任务分布到多台机器上执行就会涉及到分布式事务的场景,分布式事务一直以来都是分布式系统比较难以解决的问题。
事务的理解,比如你要将账户A转1块钱到账户B中,那么这个行为在执行时会被拆分成两个步骤,第一步是将A账户扣掉1块钱,第二步就是将B账户加上1块钱;但是这两个步骤的特点是:要么都执行成功,要么都执行失败,不能存在一个成功一个失败的情况。我们把这种多个步骤要么同时执行成功,要么同时执行失败,不允许出现中间状态的操作就叫做事务。
本地事务的理解,拿上面的转账例子来说,如果刚好A账户和B账户在同一家银行的同一个数据库里,那么他就满足了一个本地事务的基本条件;也就是说我要执行这两个账户的加减操作只需要在一个程序中就能完成,而且这两个操作彼此之间的顺序和结果是可知的,那么我们在程序内部就可以很容易实现这个事务操作;
但是如果A账户跟B账户分别在两家不同银行的不同数据库中就没有办法做到像刚才那样在同一个程序里同时去操作A账户和B账户了,我们只能先在A账户对应的银行进行第一步操作,然后再在B账户对应的银行里进行第二步操作,但还会有个问题需要注意那就是操作A账户跟操作B账户这两个操作彼此之间的结果和顺序是不可见的,而这就是分布式事务的场景;此时就只能找一个中间人来帮忙协调这个事情,而这个中间人就是银联,于是我们只需要把转账这个行为告诉银联,然后银联来具体负责向A银行账户扣钱再去B银行的账户加钱;但是这个过程其实相比于刚才的本地事务要复杂的多,因为涉及到了三方的沟通,银行A、银行B、银联,这里面一旦有某一环节处理不好就容易导致A、B账户金额的不一致;那么为了保证分布式事务的可靠性就出现了两阶段提交和三阶段提交的实现方案。
两阶段提交就是把这个多方沟通协调的过程根据沟通顺序划分为两个阶段;提交就是把写在内存中的数据再次写入到磁盘中;回滚是把在内存中修改的数据进行撤销。A账户跨行向B账户转账,第一阶段为银联收到转账申请后先向A账户所在银行发起扣钱操作,A只执行不提交也就是只在内存中对金额进行扣减但是不写入到磁盘中然后把执行成功的消息告诉银联,接着银联再向B的所在的银行发起加钱操作也只是在内存中对账户金额进行增加并不写入磁盘,然后再把执行成功的消息也告诉银联,第一阶段也可称为投票阶段,如果A、B操作都成功则投票成功,否则为失败。然后是分布式事务的第二个阶段,当银联分别收到A、B银行的操作反馈之后,确保所有步骤都没有问题便开始向A银行和B银行发出提交通知,让A银行和B银行分别将刚才在内存中修改的金额写入到磁盘中进行持久化,而这个阶段就叫做事务的提交阶段。如果两个阶段其中任何一个阶段一旦出现了某个操作的失败,那么银联就会在第一时间想办法不让A、B的账户余额变化写入磁盘中,就是进行事务的回滚操作,两阶段提交是用来保证分布式事务一致性的一种策略,但也有一些不完善的地方,然后就有三阶段提交。
三阶段提交比两阶段提交多了一个事务开始前的询问阶段,比如当银联决定开始对A、B账户进行转账操作前,为了严谨他会先询问A、B账户所在的银行当前是否可以执行对应账户余额的增减操作,如果当前A银行或者B银行的数据据刚好在维护或者升级,那么就可以第一时间通过这个第一阶段的询问来得知,这样就可以提前终止本次转账操作,这么做的好处在于提前对各个要通讯的对象系统状况有个初步的了解,如果通信对象存在网络故障、系统负载过高等问题就可以提前知道避免了后续无谓的操作,而剩下的两个阶段跟两阶段提交的步骤基本一致,三阶段提交还优化了两阶段提交的超时机制,比如在原来等银联发送提交通知给A、B银行时如果协调者银联挂了,那么银行A和银行B就只能在那里等待并等银联恢复通信;而三阶段提交的机制则优化了这一点,如果最后一个阶段银联因为各种原因无法正常通信超过一段等待时间后那么银行A和银行B就可以在不用收到银联提交通知的情况下自己完成各自的提交操作,从而进一步提高分布式事务的一致性成功率。
标签:事务,账户,银联,阶段,提交,操作,深入,分布式 From: https://blog.csdn.net/2301_79551573/article/details/136967856