(转)理解这两点,也就理解了paxos协议的精髓

转发 https://blog.csdn.net/qq_35440678/article/details/78080431

什么是paxos协议?
Paxos用于解决分布式系统中一致性问题。分布式一致性算法(Consensus Algorithm)是一个分布式计算领域的基础性问题,其最基本的功能是为了在多个进程之间对某个(某些)值达成一致(强一致);简单来说就是确定一个值,一旦被写入就不可改变。paxos用来实现多节点写入来完成一件事情,例如mysql主从也是一种方案,但这种方案有个致命的缺陷,如果主库挂了会直接影响业务,导致业务不可写,从而影响整个系统的高可用性。paxos协议是只是一个协议,不是具体的一套解决方案。目的是解决多节点写入问题。

paxos协议用来解决的问题可以用一句话来简化:

将所有节点都写入同一个值,且被写入后不再更改。
paxos的几个基本概念
一、两个操作:

Proposal Value:提议的值;
Proposal Number:提议编号,可理解为提议版本号,要求不能冲突;
二、三个角色:

Proposer:提议发起者。Proposer 可以有多个,Proposer 提出议案(value)。所谓 value,可以是任何操作,比如“设置某个变量的值为value”。不同的 Proposer 可以提出不同的 value,例如某个Proposer 提议“将变量 X 设置为 1”,另一个 Proposer 提议“将变量 X 设置为 2”,但对同一轮 Paxos过程,最多只有一个 value 被批准。
Acceptor:提议接受者;Acceptor 有 N 个,Proposer 提出的 value 必须获得超过半数(N/2+1)的 Acceptor批准后才能通过。Acceptor 之间完全对等独立。
Learner:提议学习者。上面提到只要超过半数accpetor通过即可获得通过,那么learner角色的目的就是把通过的确定性取值同步给其他未确定的Acceptor。
?三、协议过程

一句话说明是:

proposer将发起提案(value)给所有accpetor,超过半数accpetor获得批准后,proposer将提案写入accpetor内,最终所有accpetor获得一致性的确定性取值,且后续不允许再修改。
协议分为两大阶段,每个阶段又分为A/B两小步骤:

准备阶段(占坑阶段)
第一阶段A:Proposer选择一个提议编号n,向所有的Acceptor广播Prepare(n)请求。
第一阶段B:Acceptor接收到Prepare(n)请求,若提议编号n比之前接收的Prepare请求都要大,则承诺将不会接收提议编号比n小的提议,并且带上之前Accept的提议中编号小于n的最大的提议,否则不予理会。
接受阶段(提交阶段)
第二阶段A:整个协议最为关键的点:Proposer得到了Acceptor响应
如果未超过半数accpetor响应,直接转为提议失败;
如果超过多数Acceptor的承诺,又分为不同情况:
如果所有Acceptor都未接收过值(都为null),那么向所有的Acceptor发起自己的值和提议编号n,记住,一定是所有Acceptor都没接受过值;
如果有部分Acceptor接收过值,那么从所有接受过的值中选择对应的提议编号最大的作为提议的值,提议编号仍然为n。但此时Proposer就不能提议自己的值,只能信任Acceptor通过的值,维护一但获得确定性取值就不能更改原则;
第二阶段B:Acceptor接收到提议后,如果该提议版本号不等于自身保存记录的版本号(第一阶段记录的),不接受该请求,相等则写入本地。

整个paxos协议过程看似复杂难懂,但只要把握和理解这两点就基本理解了paxos的精髓:

1. 理解第一阶段accpetor的处理流程:如果本地已经写入了,不再接受和同意后面的所有请求,并返回本地写入的值;如果本地未写入,则本地记录该请求的版本号,并不再接受其他版本号的请求,简单来说只信任最后一次提交的版本号的请求,使其他版本号写入失效;

2. 理解第二阶段proposer的处理流程:未超过半数accpetor响应,提议失败;超过半数的accpetor值都为空才提交自身要写入的值,否则选择非空值里版本号最大的值提交,最大的区别在于是提交的值是自身的还是使用以前提交的。

下面通过具体案例来深刻理解这两点。

协议过程举例:

看这个最简单的例子:1个processor,3个Acceptor,无learner。

目标:proposer向3个aceptort 将name变量写为v1。

第一阶段A:proposer发起prepare(name,n1),n1是递增提议版本号,发送给3个Acceptor,说,我现在要写name这个变量,我的版本号是n1
第一阶段B:Acceptor收到proposer的消息,比对自己内部保存的内容,发现之前name变量(null,null)没有被写入且未收到过提议,都返回给proposer,并在内部记录name这个变量,已经有proposer申请提议了,提议版本号是n1;
第二阶段A:proposer收到3个Acceptor的响应,响应内容都是:name变量现在还没有写入,你可以来写。proposer确认获得超过半数以上Acceptor同意,发起第二阶段写入操作:accept(v1,n1),告诉Acceptor我现在要把name变量协议v1,我的版本号是刚刚获得通过的n1;
第二阶段B:accpetor收到accept(v1,n1),比对自身的版本号是一致的,保存成功,并响应accepted(v1,n1);
结果阶段:proposer收到3个accepted响应都成功,超过半数响应成功,到此name变量被确定为v1。

以上是正常的paxos协议提议确定流程,是不是很简单,很容易理解呢?

确定你理解了上面的例子再往后看。

这是最简单也最容易理解的例子,但真实情况远比这个复杂,还有以下问题:

如果其中的某个Acceptor没响应怎么处理?
如果只写成功了一个accpetor又怎么处理,写成功两个呢?
如果多个proposer并发写会导致accpetor写成不同值吗?
learner角色是做什么用?
为什么是超过半数同意?
paxos特殊情况下的处理
第一种情况:Proposer提议正常,未超过accpetor失败情况

问题:还是上面的例子,如果第二阶段B,只有2个accpetor响应接收提议成功,另外1个没有响应怎么处理呢?

处理:proposer发现只有2个成功,已经超过半数,那么还是认为提议成功,并把消息传递给learner,由learner角色将确定的提议通知给所有accpetor,最终使最后未响应的accpetor也同步更新,通过learner角色使所有Acceptor达到最终一致性。

第二种情况:Proposer提议正常,但超过accpetor失败情况

问题:假设有2个accpetor失败,又该如何处理呢?

处理:由于未达到超过半数同意条件,proposer要么直接提示失败,要么递增版本号重新发起提议,如果重新发起提议对于第一次写入成功的accpetor不会修改,另外两个accpetor会重新接受提议,达到最终成功。

情况再复杂一点:还是一样有3个accpetor,但有两个proposer。

情况一:proposer1和proposer2串行执行

proposer1和最开始情况一样,把name设置为v1,并接受提议。

proposer1提议结束后,proposer2发起提议流程:

第一阶段A:proposer1发起prepare(name,n2)

第一阶段B:Acceptor收到proposer的消息,发现内部name已经写入确定了,返回(name,v1,n1)

第二阶段A:proposer收到3个Acceptor的响应,发现超过半数都是v1,说明name已经确定为v1,接受这个值,不在发起提议操作。

情况二:proposer1和proposer2交错执行

proposer1提议accpetor1成功,但写入accpetor2和accpetor3时,发现版本号已经小于accpetor内部记录的版本号(保存了proposer2的版本号),直接返回失败。

proposer2写入accpetor2和accpetor3成功,写入accpetor1失败,但最终还是超过半数写入v2成功,name变量最终确定为v2;

proposer1递增版本号再重试发现超过半数为v2,接受name变量为v2,也不再写入v1。name最终确定还是为v2

情况三:proposer1和proposer2第一次都只写成功1个Acceptor怎么办

都只写成功一个,未超过半数,那么Proposer会递增版本号重新发起提议,这里需要分多种情况:

3个Acceptor都响应提议,发现Acceptor1{v1,n1} ,Acceptor2{v2,n2},Acceptor{null,null},Processor选择最大的{v2,n2}发起第二阶段,成功后name值为v2;
2个Acceptor都响应提议,
如果是Acceptor1{v1,n1} ,Acceptor2{v2,n2},那么选择最大的{v2,n2}发起第二阶段,成功后name值为v2;
如果是Acceptor1{v1,n1} ,Acceptor3{null,null},那么选择最大的{v1,n1}发起第二阶段,成功后name值为v1;
如果是Acceptor2{v2,n2} ,Acceptor3{null,null},那么选择最大的{v2,n2}发起第二阶段,成功后name值为v2;
只有1个Acceptor响应提议,未达到半数,放弃或者递增版本号重新发起提议
可以看到,都未达到半数时,最终值是不确定的!

整个过程自己也在学习,如有不对的地方欢迎指出:)

收集到一些资料可以分享下,也相当于分享自己的学习过程:

1. 首先,推荐的是知行学社的《分布式系统与Paxos算法视频课程》: ,视频讲的非常好,很适合入门,循序渐进慢慢推导,我自己看了不下5遍,视频讲解理解更深,推荐大家都看看,视频末尾说有后续介绍,一直没有找到,如果有哪位大侠找到了通知下我,不胜感激。

2. 推荐刘杰的《分布式系统原理介绍》 ,里面有关于paxos的详细介绍,例子非常多,也有包括paxos协议的证明过程,大而全,质量相当高的一份学习资料!

3. 推荐的一份高质量ppt《可靠分布式系统基础 Paxos 的直观解释》,虽然是只是一份ppt没有讲解视频,但看ppt也能理解整个的paxos介绍和推导过程,写的很具体,配图很清晰明了;

4. 微信的几篇公众号文章:《微信PaxosStore:深入浅出Paxos算法协议》(微信PaxosStore:深入浅出Paxos算法协议 )、《微信开源:生产级paxos类库PhxPaxos实现原理介绍》(微信自研生产级paxos类库PhxPaxos实现原理介绍 ),文章写的都挺好,但是博文有个缺点是知识比较零散,不适合入门,需要有一定基础才好理解;

5. 技术类的东西怎么能只停留在看上面,肯定要看代码啊,推荐微信开源的phxpaxos:https://github.com/tencent-wechat/phxpaxos,结合代码对协议理解更深,很多时候说了一大堆看代码就是一个if或者for循环,看了代码豁然开朗。

6. 如果英文可以的话,一定要看看paxos作者Lamport《paxos made simple》的论文。

总结
Paxos协议是用来解决分布式系统中一致性问题的其中一种解决方案。协议过程看似羞涩难懂,只要理解accpetor接收阶段的不同处理流程和proposer提议阶段的处理流程,也就基本掌握了paxos协议的精髓,处理流程也不复杂,只是异常条件分支较多,只要一个个去理解也没什么难度,比我们写的业务流程简单多了。

最最后,如果有哪里写的不对的地方,欢迎指出共同学习,共同进步!
---------------------
作者:yinnnnnnn
来源:CSDN
原文:https://blog.csdn.net/qq_35440678/article/details/78080431
版权声明:本文为博主原创文章,转载请附上博文链接!

原文地址:https://www.cnblogs.com/robinfox/p/10036151.html

时间: 2024-10-04 00:40:21

(转)理解这两点,也就理解了paxos协议的精髓的相关文章

javascript深入理解js闭包(个人理解,大神勿喷)

一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量. Js代码 var n=999; function f1(){ alert(n); } f1(); // 999 另一方面,在函数外部自然无法读取函数内的局部变量. Js代码 function f1(){ var n=999; } alert(n); // error 这里有一个地方需要注意,函数

[论文理解]关于ResNet的进一步理解

[论文理解]关于ResNet的理解 这两天回忆起resnet,感觉残差结构还是不怎么理解(可能当时理解了,时间长了忘了吧),重新梳理一下两点,关于resnet结构的思考. 要解决什么问题 论文的一大贡献就是,证明了即使是深度网络,也可以通过训练达到很好的效果,这跟以往的经验不同,以往由于网络层数的加深,会出现梯度消失的现象.这是因为,在梯度反传的时候,由于层数太深,传递过程又是乘法传递,所以梯度值会越乘越小,梯度消失在所难免.那么怎么才能解决这个问题呢?resnet提供了很好的思路. 怎么解决

0220自学Linux_逻辑理解用户进程权限相关+理解文件内各字段(passwd,shadow,group)

11 内核是真正意义上的操作系统 库有动态库也有静态库,Linux的动态库是.so后缀的,也称为共享库 库是不能够独立运行的,只能被调用 Window的动态库是.dll后缀的 我们平时所谓的安装操作系统是装在硬盘上的 我们对于系统而言,最基本的程序就是shell,不然我们无法和系统交互,打开一个命令行窗口,就打开了一个shell进程 硬件之上的是内核,内核之上是进程 如果进程中他需要调用库,那首先启动这个程序,他的进程会把这个调用的库装入内存 ,而如果是共享库,其他进程调用的话就直接在内存调用这

理解 React,但不理解 Redux,该如何通俗易懂的理解 Redux?

作者:Wang Namelos链接:https://www.zhihu.com/question/41312576/answer/90782136来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. . React有props和state: props意味着父级分发下来的属性,state意味着组件内部可以自行管理的状态,并且整个React没有数据向上回溯的能力,也就是说数据只能单向向下分发,或者自行内部消化.理解这个是理解React和Redux的前提.2. 一般构建的R

java ByteBuffer flip()和limit()的理解, 转载的, 从里面理解到flip()的作用, 想象一下 老式打字机

先列点代码片段: // ... // // 此段代码功能为从 t.txt 里复制所有数据到 out_j.txt: // ... 1 FileChannel fcin = new FileInputStream( "d:/t.txt" ).getChannel(); 2 FileChannel fcout = new FileOutputStream( new File( "d:/out_j.txt" )).getChannel();3 ByteBuffer buff

02,计算机组成与操作系统的理解、对程序的理解、OS发展史 以及 一些杂项

这里马哥讲了好多,能听懂,但需要记得东西好少,不过我还是 按照 我 对 计算机 的 理解 画了 一张 图, 不一定 准确 , 但是 差不多 把, 计算机 底层 是 由 运算器.控制器.存储器.输入设备.输出设备 这 五大部件 组成 的 其中 运算器 和 控制器 是 在 cpu 中 的, 运算器 是 负责 计算 的, 控制器 是 负责 控制 程序 流程 的,也 负责 控制 存储器 中 的 数据, 北桥 是 一个 高速 I/O 设备, 他 通常 用来 连接 内存,硬盘,显卡 等 需要 高速 I/O

理解 React,但不理解 Redux,该如何通俗易懂的理解 Redux?(转)

作者:Wang Namelos 链接:https://www.zhihu.com/question/41312576/answer/90782136来源:知乎 解答这个问题并不困难:唯一的要求是你熟悉React.不要光听别人描述名词,理解起来是很困难的.从需求出发,看看使用React需要什么:1. React有props和state: props意味着父级分发下来的属性,state意味着组件内部可以自行管理的状态,并且整个React没有数据向上回溯的能力,也就是说数据只能单向向下分发,或者自行内

对面向对象的理解和this static的理解

对象理解 JAVA语言是直接面向对象的语言,与以往的 当在一段代码块定义一个变量时,Java 就在栈中为这个变量分配内存空间,当超过变量的作用域后(比如,在函数A中调用函数B,在函数B中定义变量a,变量a的作用域只是函数B,在函数B运行完以后,变量a会自动被销毁.分配给它的内存会被回收),Java 会自动释放掉为该变量分配的内存空间,该内存空间可以立即被另作它用本不同是:它的设计出发点更能直接的描述问题域中客观存在的事物. 对象用计算机语言来对问题域中事物的描叙,对象通过"属性"和&q

递归函数的深入理解,很多人的理解误区

很久没时间发笔记了,这次抽空 sky(我的昵称) 再为大家讲解一个东东,讲的不好之处大神勿喷哈 #include<iostream>using namespace std;void bin(const unsigned int &i){        if (i/2)        bin(i/2);    cout << i%2;} int main(){    int a;    cin >> a;    bin(a);    cout << e