大数据日志录-一致性协议-两阶段提交协议
《大数据日志录》此书对一致性协议介绍的比较多和深,这里拆成单独的一篇文章,去重点理解下两阶段提交协议。
什么是两阶段提交协议?
两阶段提交协议是很常用的解决分布式事务问题的方式,它可以保证在分布式事务中,要么所有参与进程都提交事务,要么都取消事务,即实现ACID中的原子性。
两阶段协议中,存在两类实体:唯一的协调者和众多的参与者。协调者起到分布式事物的管理协调作用。
两阶段协议具体过程?
表决阶段(Voting)和提交阶段(Commit),假设在没有故障情况下,两阶段提交协议由以下操作做成:
表决阶段
【协调者】协调者向所有的参与者发出VOTE_REQUEST消息。
【参与者】当参与者收到VOTE_REQUEST消息后,如果自身准备好,参与者可以向协调者发送一个VOTE_COMMIT消息,否则要发送一个VOTE_ABORT消息。
提交阶段
【协调者】如果协调者在表决阶段收到了所有的参与者的VOTE_COMMIT消息,那么协调者此时会再发一个GLOBAL_COMMIT消息,通知所有的参与者可以进行本地提交。如果协调者在表决阶段收到了哪怕只有一条VOTE_ABORT消息,那么协调者会决定取消事务,会向所有参与者发布一条GLOBAL_ABORT消息通知其取消事务。
【参与者】参与者收到GLOBAL_COMMIT消息,则提交本地事务,否则如果收到GLOBAL_ABORT消息,则参与者取消本地事务。
状态转换
上图是协调者的状态有限机。初始化状态为INIT,发出VOTE-REQUEST消息后,变为WAIT状态。在WAIT状态下会收到参与者的消息,假如收到的是VOTE_ABORT,协调者则会发出GLOBAL-ABORT消息,其自身状态转换为ABORT阶段。假如收到的是VOTE_COMMIT,则会发出GLOBAL-COMMIT消息,其自身状态转换为COMMIT阶段。
上图是参与者的状态转换,初始阶段为INIT阶段,收到VOTE-REQUEST消息后,自身准备好,则发出VOTE-COMMIT消息,并转换为READY阶段。如果没有准备好,则切换发出VOTE-ABORT消息,并转换为ABORT阶段。如果在READY阶段,收到协调者的GLOABL_ABORT消息,则转为ABORT阶段,否则转换为COMMIT阶段。
两阶段协议存在的问题
阻塞问题比较严重,协调者的WAIT状态,参与者的READY状态,参与者INIT状态。都需要等待对方的回馈,如果这段时间一直没有回馈,就是一直处于阻塞状态。如何解决该问题呢?
超时机制+参与者互询问机制,两个机制互相保证。
超时机制这个比较好理解。
协调者处于WAIT状态,在限定时间内没有收到消息,则可以认为参与者崩溃或者网络问题,则可以进一步发出GLOBAL_ABORT取消事务。
参与者处于INIT状态,在限定时间内没有收到协调者发出的VOTE-REQUEST消息,则可向协调者发出VOTE-ABORT消息,中断后续的执行。
参与者互相询问机制
这个主要是针对处于READY状态的参与者,如果单纯的靠超时机制,超时则中断,不合适。因为处于这个状态的参与者就在等协调者的GLOBAL_COMMIT或者GLOBAL_ABORT消息,如果直接执行事务中断,取消事务,可能会造成数据不一致,因为这时其他参与者收到的可能是GLOBAL_COMMIT消息。这个时候就需要有参与者之间互相询问的机制。
假设当前的参与者为P。它的第一个询问者为Q,以下为具体流程:
假设Q是COMMIT状态,那么证明协调者已经发出过GLOBAL_COMMIT消息了,可能是因为自身网络问题没收到,那么P要执行本地事务,并切换到COMMIT状态。
假设Q是INIT状态。Q还没有收到VOTE-REQUEST消息,有可能是Q出现网络问题或者故障,那么根据2PC协议来看,如果还在超时时间之内,协调者这个时候,还在等待Q的VOTE-COMMIT消息,既然Q是INIT状态,必然是不会发出VOTE-COMMIT消息。那么协调者后续就会发出GLOBAL_ABORT消息,将所有参与者置为ABORT状态,那么此时P根据Q的INIT状态,可以自动切换到ABORT状态。
假设Q是ABORT状态,可能是Q自身未准备好,或者协调者已经发出GLOBAL-ABORT消息,那么根据2PC协议来看,这个时候P可以切换至ABORT状态。
假设Q是READY状态,那么这个时候P就得去询问其他参与者。根据其他参与者的状态去判断,一开始这里有个问题,如果其他参与者也都是READY状态,但是又想了下状态的变更也是有超时时间的,最终状态也都是会变更的。
总结
以上就是2PC的所有内容,重要的是整个协议的过程,以及参与者和协调者是如何变更状态的,后面还有3PC协议,后面找时间再研究下3PC协议。