其实三者都是为了解决分布式一致性问题而存在的协议和算法。首先先来了解几个概念。

协调者(coordinator):在分布式系统中,当事务操作需要跨越多个分布式节点的时候,为了保持分布式处理的ACID特性,需要引入它来统一调度所有节点的执行逻辑。

参与者(participant):协调者调度的这些节点就是参与者了

在实际的过程中,协调者负责调度参与者的行为,并最终决定这些参与者是否要把事务真正进行提交。

一:二阶段提交协议
1.投票阶段

  • 协调者向所有的参与者发送事务的内容,询问是否可以执行事务,提交操作然后等待参与者的回复。
  • 参与者节点收到讯息,执行事务操作,并将undo和redo信息记录到日志信息中。
  • 然后参与者将是否执行事务的结果反馈给协调者,如果成功执行就返回Yes否则返回No。

2.执行阶段
2.1如果都是返回Yes,则执行事务提交

  • 协调者向所有的参与者节点发出commit请求。
  • 参与者收到commit的请求后,会正式的执行事务并提交。完成提交之后释放所有的事务资源。
  • 参与者完成提交之后会向协调者发送ack的消息。
  • 协调者收到ack之后表示此次事务完成。

2.2如果有返回是No,则执行中断事务

  • 协调者向所有的参与者节点发送Rollback的请求。
  • 参与者收到请求后会利用其在第一阶段记录的undo日志信息来执行事务回滚操作。释放资源。
  • 完成回滚之后,参与者会向协调者发送ack的消息。
  • 协调者收到所有的参与者的ack之后,完成事务中断。

一阶段

Android 协调者 协调者是什么意思_java


二阶段

Android 协调者 协调者是什么意思_Android 协调者_02

那么二阶段提交会有哪些问题呢?
首先,由于投票阶段需要等待所有的都给协调者反馈才会进行下一个阶段,那么显而易见的出现了同步阻塞的问题。每个参与者都会等待,直到到了下一个阶段。
其次,我们考虑这么一种情况,如果协调者挂了,是不是都会一直等待?这也就是我们所说的单点问题。
再然后,如果在二阶段在协调者发送commit的时候出现了局部的网络异常,导致有一部分参与者收到了消息,一部分参与者并没有收到消息,这就导致了数据的不一致。
最后,这种方式其实他过于的保守了。

二:三阶段提交
1.canCommit阶段
协调者发送cancommit的请求。参与者返回是否可以的响应。
2.preCommit阶段
2.1若canCommit阶段都是返回的Yes则直接preCommit,各个参与者记录预提交的redo和undo日志。
2.2若有返回为No的参与者,协调者向所有的参与者发送abort命令。或者等待超时后参与者直接中断事务。
3.doCommit阶段
3.1若都成功,则直接返回ack,参与者提交事务,完成整个流程。
3.2若协调者发现其中的参与者有发送No的,则向所有的参与者发送abort,参与者接到消息或者等待超时后中断任务,进行事务回滚。
仔细的同学可能发现了,如果第三阶段我协调者挂了,或者说出现协调者和参与者无法通信,其他的参与者还是会执行doCommit,那不是必定出现数据不一致嘛?是的,这就是三阶段提交的缺点,但是相较于二阶段提交,它很大程度上减小了参与者的阻塞范围,并且就算出现单点问题最后参与者还是能达成一致,这是我们希望看到的。