数据一致性指:在分布式环境下如何让一组节点达成共识,共识的内容包括:变量的值、行为或者决定的过程。一致性可以使分布式系统看上去像一个整体。
一致性通常可以用来:
- 决定是否在数据库执行一个事务
- 同步时钟的当前时间
- 执行分布式算法的下一个阶段(replicated state machine)
- leader选举
一个一致性协议是正确的,当且仅当:
- Agreement:所有N个节点共同决定同一个变量的值
- Validity:变量的值一定是由N个节点中的某些节点提议的
- Termination:所有节点最终会决定变量的值
2PC是一种最简单最直接的一致性协议,包括两个阶段:
- 第一阶段:向每个参与者发送提议,并且收集回复
- 第二阶段:把投票的结果发送给参与者,并且决定commit或者rollback
2PC在执行过程中可能发生协调者或者参与者突然宕机的情况,在不同时期宕机可能有不同的现象。
这种情况其实比较好解决,只要找一个协调者的替代者。当他成为新的协调者的时候,询问所有参与者的最后那条事务的执行情况,他就可以知道是应该做什么样的操作了。所以,这种情况不会导致数据不一致。
这种情况其实也比较好解决。如果协调者挂了。那么之后的事情有两种情况:
- 挂了就挂了,没有再恢复。那就挂了呗,反正不会导致数据一致性问题。
- 挂了之后又恢复了,这时如果他有未执行完的事务操作,直接取消掉,然后询问协调者目前我应该怎么做,协调者就会比对自己的事务执行记录和该参与者的事务执行记录,告诉他应该怎么做来保持数据的一致性。
这种情况比较复杂,我们分情况讨论。
由于这时还没有执行commit操作,新选出来的协调者可以询问各个参与者的情况,再决定是进行commit还是roolback。因为还没有commit,所以不会导致数据一致性问题。
这种情况下,当新的协调者被选出来之后,他同样是询问所有的参与者的情况。只要有机器执行了abort(roolback)操作或者第一阶段返回的信息是No的话,那就直接执行roolback操作。如果没有人执行abort操作,但是有机器执行了commit操作,那么就直接执行commit操作。这样,当挂掉的参与者恢复之后,只要按照协调者的指示进行事务的commit还是roolback操作就可以了。因为挂掉的机器并没有做commit或者roolback操作,而没有挂掉的机器们和新的协调者又执行了同样的操作,那么这种情况不会导致数据不一致现象。
这种情况下,新的协调者被选出来之后,如果他想负起协调者的责任的话他就只能按照之前那种情况来执行commit或者roolback操作。这样新的协调者和所有没挂掉的参与者就保持了数据的一致性,我们假定他们执行了commit。但是,这个时候,那个挂掉的参与者恢复了怎么办,因为他之前已经执行完了之前的事务,如果他执行的是commit那还好,和其他的机器保持一致了,万一他执行的是roolback操作那?这不就导致数据的不一致性了么?虽然这个时候可以再通过手段让他和协调者通信,再想办法把数据搞成一致的,但是,这段时间内他的数据状态已经是不一致的了!
2PC是一致性协议里面最简单的协议,因为它的简单,很多系统都选择使用2PC协议。2PC最大的问题是:如果出现协调者和参与者都挂了的情况,有可能导致数据不一致。