设为首页 加入收藏

TOP

一篇文章让你弄懂分布式一致性协议Paxos(二)
2023-09-23 15:44:33 】 浏览:156
Tags:一篇 文章让 Paxos
2或1693702932000.1、1693702932000.2、1693702932000.3;
每个Proposer在发起Prepare请求后如果没有得到超半数响应时,会更新自己的提案号,再重新发起新一轮的Prepare请求。

  • 提案值

提案值的定义也完全是根据自身的业务需求定义的。在实际应用场景中,提案值可以是具体的数值、字符串或是cmd命令或运算函数等任何形式,比如在分布式数据库的设计中,我们可以将数据的写入操作、修改操作和删除操作等作为提案值。

3、最终值的选择

Acceptor每次同意新的提案值都会将消息同步给Learner,Learner根据各个Acceptor的反馈判断当前是否已超过半数同意,如果达成共识则发送广播消息给所有Acceptor和Proposer并结束提案。
在实际业务场景中,Learner可能由多个节点组成,每个Learner都需要“学习”到最新的投票结果。关于Learner的实现,Lamport在其论文中给出了下面两种实现方式:

(1)、选择一个Learner作为主节点用于接收投票结果(即accepted消息),其他Learner节点作为备份节点,Learner主节点接收到数据后再同步给其他Learner节点。该方案缺点:会出现单点问题,如果这个主节点挂掉,则不能获取到投票结果。
(2)、Acceptor同意提案后,将投票结果同步给所有的Learner节点,每个Learner节点再将结果广播给其他的Learner节点,这样可以避免单点问题。不过由于这种方案涉及很多次的消息传递,所以效率要低于上述的方案。

三、活锁问题

1、什么是活锁?

“活锁”指的是任务由于某些条件没有被满足,导致一直重复尝试,失败,然后再次尝试的过程。 活锁和死锁的区别在于,处于活锁的实体是在不断的改变状态,而处于死锁的实体表现为等待(阻塞);活锁有可能自行解开,而死锁不能。

2、为什么Basic-Paxos可能会出现活锁?

由于Proposer每次发起prepare请求都会更新编号,那么就有可能出现这种情况,即每个Proposer在被拒绝时,增大自己的编号重新发起提案,然后每个Proposer在新的编号下不能达成共识,又重新增大编号再次发起提案,一直这样循环往复,就成了活锁。活锁现象就是指多个Proposer之间形成僵持,在某个时间段内循环发起preapre请求,进入Accept阶段但不能达成共识,然后再循环这一过程的现象。
活锁现象示例图:

3、活锁如何解决?

活锁会导致多个Proposer在某个时间段内一直不断地发起投票,但不能达成共识,造成较长时间不能获取到共识结果。活锁有可能自行解开,但该过程的持续时间可长可短并不确定,这与具体的业务场景实现逻辑、网络状况、提案重新发起时间间隔等多方面因素有关。
解决活锁问题,有以下常见的方法:
(1)、当Proposer接收到响应,发现支持它的Acceptor小于半数时,不立即更新编号发起重试,而是随机延迟一小段时间,来错开彼此的冲突。
(2)、可以设置一个Proposer的Leader,集群全部由它来进行提案,等同于下文的Multi-Paxos算法。

四、Multi-Paxos

上文阐述了Paxos算法的基础运算流程,但我们发现存在两个问题:
(1)、集群内所有Proposer都可以发起提案所以Basic Paxos算法有可能导致活锁现象的发生;
(2)、每次发起提案都需要经过反复的Prepare和Accept流程,需要经过很多次的网络交互,影响程序的执行效率。
考虑到以上两个问题,能不能在保障分布式一致性的前提下可以避免活锁情况的发生,以及尽可能减少达成共识过程中的网络交互,基于这种目的随即产生了Multi-Paxos算法。

首先我们可以设想一下:在多个Proposer的环境中最理想的达成共识的交互过程是什么样子的?
就是这样一种情况:集群中的某个Proposer发送一次广播prepare请求并获得超半数响应,然后再发送一次广播accept请求,并获得超过半数的同意后即达成共识。但现实中多个Proposer很可能会互相交错的发送消息,彼此之间产生冲突,而且在不稳定的网络环境中消息发送可能会延迟或丢失,这种情况下就需要再次发起提案,影响了执行效率。Multi-Paxos算法就是为了解决这个问题而出现。

Multi-Paxos算法是为了在保障集群所有节点平等的前提下,依然有主次之分,减少不必要的网络交互流程。
Multi-Paxos算法是通过选举出一个Proposer主节点来规避上述问题,集群中的各个Proposer通过心跳包的形式定期监测集群中的Proposer主节点是否存在。当发现集群中主节点不存在时,便会向集群中的Acceptors发出申请表示自己想成为集群Proposer主节点。而当该请求得到了集群中的大多数节点的同意后随即该Proposer成为主节点。
集群中存在Proposer主节点时,集群内的提案只有主节点可以提出,其他Proposer不再发起提案,则避免了活锁问题。由于集群中只有一个节点可以发起提案,不存在冲突的可能,所以不必再发送prepare请求,而只需要发送accept请求即可,因此减少了协商网络交互次数。

五、Paxos应用场景示例

上文对Paxos算法的处理流程就行了阐述,为了加深理解,下面以一个分布式数据库的使用案例来阐述Paxos算法在实际业务场景中的使用。

场景描述:分布式数据库中假设包含3个节点,客户端访问时通过轮询或随机访问的方式请求到其中的某个节点,我们要通过Paxos算法保证分布式数据库的3个节点中数据的一致性。
实际的分布式数据一致性流程更为复杂,我这里为了方便阐述将这个过程进行一些简化。

分布式数据库中的每个节点都存储三份数据,一是事务日志数据,二是DB数据,三是事务日志执行位置。
事务日志表存储着数据库的操作日志记录,包括:写入Put、修改Update和删除Delete等相关的操作日志,有些文章资料将事务日志表称为状态机其实是一个意思。
DB数据表存储具体的业务数据。
事务日志执行位置用于记录当前节点执行到了哪一条操作记录;

整体设计思想:我们只要通过Paxos算法保证各个节点事务日志表数据一致就可以保证节点数据的一致性。

假设,当前各个节点的事务日志表和数据表均为空,现在客户端1对数据库发起写入操作请求:{'Op1','Put(a,'1')'},这里的Op1代表操作的ID(为了简单起见,直接使用自增ID表示,该数值对应Paxos算法中的提案编号),Put(a,'1')代表操作内容,对应Paxos中的提案值,假设该请求被随机分配到了Server1处理。

流程说明:
1、Server1接受到Put(a,'1')请求,并不是直接写入数据表,而是首先通过Paxos算法判断集群节点是否达成写入共识;
2、当前三个节点的OperateIndex均为0,事务日志表和数据表均为空,Server1的Proposer首先向三个节点发起Prepare(OperateIndex + 1),即Prepare(1)请求。
3、接收到过半数的Prepare请求反馈后,发送Accept(1,'Put(a,'1')')请求,并得到Accepted请求反馈,则此时三个节

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇8K Star,一款开源仿Notion且AI强.. 下一篇15.3K Star,超好用的开源协作式..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目