1. 2PC(两阶段提交)
如上所示是2阶段提交的一个过程,可为什么要进行两阶段提交呢?这里主要来说是将操作事务能力和提交、回滚事务能力分开来做成2阶段,如果不分开会造成什么后果呢:
- 如果单纯 A 向 B 发送一个请求就以一次结束(没有区分操作、提交事务),那么如果请求发出去了,没有收到消息,我们是认为请求执行成功了还是失败了?
- 假如是一个收藏点击自增操作,需要远程接口调用另一个服务,如果是操作成功了,但是由于网络波动导致中间消息没了,那么我执行回滚操作,但是这时候消息可能是由于阻塞了,导致消息又传回了A,那么A还是可能会处理剩下的一些事务操作,导致数据不一致,也就是没保留住服务的原子性问题
- 所有服务的数据处理要么都成功要么都失败,即所有服务的原子性问题
再对两阶段提交进行详细介绍,如上所示,在两阶段提交中,主要涉及到两个角色,分别是协调者和参与者:
- 第一阶段:当要执行一个分布式事务的时候,事务发起者首先向协调者发起事务请求,然后协调者会给所有参与者发送 prepare 请求(其中包括事务内容)告诉参与者你们需要执行事务了,如果能执行我发的事务内容那么就先执行但不提交,执行后请给我回复。然后参与者收到 prepare 消息后,他们会开始执行事务(但不提交),并将Undo和Redo信息记入事务日志中,之后参与者就向协调者反馈是否准备好了
- 第二阶段:第二阶段主要是协调者根据参与者反馈的情况来决定接下来是否可以进行事务的提交操作,即提交事务或者回滚事务
其实二阶段提交还是比较拉跨的,虽然解决了服务的原子性问题,但是也带来很多其它问题:
- 单点故障问题:如果协调者挂了那么整个系统都处于不可用的状态了。
- 阻塞问题:即当协调者发送 prepare 请求,参与者收到之后如果能处理那么它将会进行事务的处理但并不提交,这个时候会一直占用着资源不释放,如果此时协调者挂了,那么这些资源都不会再释放了,这会极大影响性能。
- 数据不一致问题:比如当第二阶段,协调者只发送了一部分的 commit 请求就挂了,那么也就意味着,收到消息的参与者会进行事务的提交,而后面没收到的则不会进行事务提交,那么这时候就会产生数据不一致性问题
2. 3PC(三阶段提交)
- CanCommit 阶段:协调者向所有参与者发送 CanCommit 请求,参与者收到请求后会根据自身情况查看是否能执行事务,如果可以则返回 YES 响应并进入预备状态,否则返回 NO (超时中断)
- PreCommit 阶段:协调者根据参与者返回的响应来决定是否可以进行下面的 PreCommit 操作。如果上面参与者返回的都是 YES,那么协调者将向所有参与者发送 PreCommit 预提交请求,参与者收到预提交请求后,会进行事务的执行操作,并将 Undo 和 Redo 信息写入事务日志中 ,最后如果参与者顺利执行了事务则给协调者返回成功的响应。如果在第一阶段协调者收到了 任何一个 NO 的信息,或者 在一定时间内 并没有收到全部的参与者的响应,那么就会中断事务,它会向所有参与者发送中断请求(abort),参与者收到中断请求之后会立即中断事务,或者在一定时间内没有收到协调者的请求,它也会中断事务(超时中断)
- DoCommit 阶段:这个阶段其实和 2PC 的第二阶段差不多,如果协调者收到了所有参与者在 PreCommit 阶段的 YES 响应,那么协调者将会给所有参与者发送 DoCommit 请求,参与者收到 DoCommit 请求后则会进行事务的提交工作,完成后则会给协调者返回响应,协调者收到所有参与者返回的事务提交成功的响应之后则完成事务。若协调者在 PreCommit 阶段 收到了任何一个 NO 或者在一定时间内没有收到所有参与者的响应 ,那么就会进行中断请求的发送,参与者收到中断请求后则会 通过上面记录的回滚日志 来进行事务的回滚操作,并向协调者反馈回滚状况,协调者收到参与者返回的消息后,中断事务(超时中断)
注意的点:3PC 在 DoCommit 阶段参与者如未收到协调者发送的提交事务的请求,它会在一定时间内进行事务的提交,因为参与者有理由相信,已经走到这一步的时候,协调者已经完成了一阶段、二阶段除参与者返回yes阶段的任务,如果实在执行失败大不了进行log日志回滚即可(这里没考虑出现其它参与者和协调者挂了或网络分区问题)
但是这里 3PC 通过一系列的超时机制很好的缓解了阻塞问题,但是最重要的一致性并没有得到根本的解决,比如在 DoCommit 阶段,当一个参与者收到了请求之后其他参与者和协调者挂了或者出现了网络分区,这个时候收到消息的参与者都会进行事务提交,这就会出现数据不一致性问题
3. Paxos 算法
- Paxos 算法是基于消息传递且具有高度容错特性的一致性算法,是目前公认的解决分布式一致性问题最有效的算法之一,其解决的问题就是在分布式系统中如何就某个值(决议)达成一致
- 在 Paxos 中主要有三个角色,分别为Proposer提案者、Acceptor表决者、Learner学习者。Paxos 算法和 2PC 一样,也有两个阶段,分别为 Prepare 和 accept 阶段。