先讲一个故事。

从前,在国王Leslie Lamport的统治下,有个黑暗的希腊城邦叫paxos。城邦里有3类人,

  • 决策者
  • 提议者
  • 群众

虽然这是一个黑暗的城邦但是很民主,按照议会民主制的政治模式制订法律,群众有什么建议和意见都可以写提案交给提议者,提议者会把提案交给决策者来决策,决策者有奇数个,为什么要奇数个?很简单因为决策的方式很无脑,少数服从多数。最后决策者把刚出炉的决策昭告天下,群众得知决策结果。

等一下,那哪里黑暗呢?问题就出在“提议者会把提案交给决策者来决策”,那么多提案决策者先决策谁的?谁给的钱多就决策谁的。

那这样会有几个问题,决策者那么多,怎么保证最后决策的是同一个提案,以及怎么保证拿到所有提议者中最高的报价。

聪明又贪婪的决策者想到了一个办法:分两阶段报价

第一阶段

  1. 决策者接受所有比他当前持有报价高的报价,且不会通知之前报价的人
  2. 提议者给所有决策者报价,若有人比自己报价高就加价,有半数以上决策者接受自己报价就停止报价。

第一阶段结束的状态

每个提议者都觉得有半数以上的大佬接受了自己的提案,很开心。而决策者集团此刻的状态是一致的,半数以上同意的提案只有一个,这个就是报价最高的(因为高的总是可以覆盖低的),具体是谁提的who care,一致就行。

第二阶段

提议者去找收过自己钱的大佬签合同,这里有3种情况:

  1. 大佬都收了别人更高的价,回去拿钱继续贿赂,回到第一阶段重新升级;
  2. 大佬收到的最高报价是自己的,美滋滋,半数以上成功签合同,提案成功;
  3. 提议者回去拿钱回来继续贿赂的时候发现合同已经被签了且半数以上都签了这个提案,不干了,赶快把自己的提案换成已经签了的提案,再去提给所有大佬,看看能不能分一杯羹遇见还没签的大佬。

第二阶段结束的状态

所有提议者手头的提案都是一样的,因为有“赶快把自己的提案换成已经签了的提案”这一步;决策者集团所有成员最终接受的提案是一样的。

好的目的已经达到了,把这个提案昭告天下,让所有群众知道这件事。

故事说完了,用正确的姿势再简单介绍下paxos

分布式系统中的节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing)。

paxos作为基于消息传递通信模型的分布式系统,不可避免的会发生以下错误:进程可能会慢、被杀死或者重启,消息可能会延迟、丢失、重复,在基础 Paxos 场景中,先不考虑可能出现消息篡改即拜占庭错误的情况。

Paxos算法解决的问题是在一个可能发生上述异常的分布式系统中如何就某个值达成一致,保证不论发生以上任何异常,都不会破坏决议的一致性。一个典型的场景是,在一个分布式数据库系统中,如果各节点的初始状态一致,每个节点都执行相同的操作序列,那么他们最后能得到一个一致的状态。

为保证每个节点执行相同的命令序列,需要在每一条指令上执行一个“一致性算法”以保证每个节点看到的指令一致。一个通用的一致性算法可以应用在许多场景中,是分布式计算中的重要问题。

Paxos用于解决分布式系统中一致性问题,在一个Paxos过程只批准一个value,只有被prepare的value且被多数Acceptor接受才能被批准,被批准的value才能被learner。在paxos算法中,分为4种角色:

  • Acceptor:决策者
  • Proposer :提议者
  • Client:产生议题者(群众)
  • Learner:最终决策学习者(群众)

阶段一

  1. Proposer向半数以上的Acceptor发送Prepare请求并附上编号N。
  2. 若Acceptor收到一个编号为N的Prepare请求,且N大于该Acceptor已经响应过的所有Prepare请求的编号,那么它就会将它已经接受过的编号最大的提案(如果有的话)作为响应反馈给Proposer,同时该Acceptor承诺不再接受任何编号小于N的提案。
  3. Proposer若没有得到半数以上Acceptor的响应,则编号+1继续发起请求。

阶段二

  1. 如果Proposer收到半数以上Acceptor对其发出的编号为N的Prepare请求的响应,那么它就会发送一个[N,提案]Accept请求给半数以上的Acceptor。
  2. 如果Acceptor收到一个针对编号为N的提案的Accept请求,只要该Acceptor没有对编号大于N的Prepare请求做出过响应,它就接受该提案

看故事的时候不知道大家有没有疑问,我是有的。

决策者Acceptor为什么要多个?

若只有一个acceptor多个proposer,acceptor可以选任意一个提案,很美好,但是有单点问题。

为什么要用“半数以上通过”这个办法来决策?

一个集合不可能同时存在两个半数以上的子集,过半的思想保证提交的value在同一时刻在分布式系统中是唯一的一致的。这种提交方式不管proposer接受到的消息是接受了谁的提议过半,只保证是有提议过半了的。然后再在第二阶段确定这个过半了的提议,让所有节点知道这件事。因此算法如果能保证value被半数acceptor接受,则意味这此时被认定的value是唯一的。

为什么acceptor要接受多个提案?

如果acceptor只能够接受一个提案,则可能发生所有proposer提出的提案都无法达到多数,决策者接收一个就结束了,状态无法一致。

当Proposer有很多个的时候,会有什么问题?

很难有一个proposer收到半数以上的回复,进而不断地执行第一阶段的协议,决策收敛速度慢,很久都不能做出一个决策。

提案为什么要带上编号(即故事中用来贿赂的钱)?

带上编号是为了决策者可以在自身接受到的提案的对比中做出最终的唯一决策。

试想如果按照提案到达时间对比提案,且不说这样就变成了只接收一个第一到达的提案,还可能因为网络原因每个决策者接受到的提案的先后顺序不一样,凉凉。

接着上面的问题,那如果把所有决策者收到的提案汇集起来选出个时间最早的呢?

把提案汇集,这时候肯定需要一个master来做判断,大家有没发现这个master好像就变成了propser,它拿到最早的提案,交给决策者...
其实,这就演变成了paxos的变种协议。

后记

为了避免竞争,加快收敛的速度,有人在算法中加入leader来代替propser,且leader在集群中只有一位,也就是说只有leader有权提议。这时leader会有单点问题,于是又加入了leader选举机制保证健壮性,到目前为止paxos演变的越来越像我下一篇要讲的zab协议了。

为了能讲得更通俗,很多地方讲得不够严谨,见谅,有问题可以提出交流。

其实这篇和zookeeper的关系不太大算是讲zab之前做的一个铺垫吧。

讲一个关于paxos的故事...的更多相关文章

  1. 一步步做程序优化-讲一个用于OpenACC优化的程序(转载)

    一步步做程序优化[1]讲一个用于OpenACC优化的程序 分析下A,B,C为三个矩阵,A为m*n维,B为n*k维,C为m*k维,用A和B来计算C,计算方法是:C = alpha*A*B + beta* ...

  2. 来来来,有讲一个吐血的故事(matlab)之脚本运行路径是什么

    脚本运行路径是什么,这真是太重要!! 重要1:你默认保存的路径 重要2:你访问的相对路径 先放图: 再看一幅图: 我的操作,点击左侧的文件夹,使上框的显示栏路径不一样,再点击运行,发现pwd指示的路径 ...

  3. 讲一个关于RSA加密算法的故事

    有甲乙两个人,甲有两把钥匙,一把叫做甲的公钥,另一把叫做甲的私钥.乙同样有两把钥匙,一把叫做乙的公钥,另一把叫做乙的私钥. 某一天,甲乙成为了好朋友,甲想向乙发送一份保密数据,这份保密数据要求只有甲乙 ...

  4. 【C#进阶系列】01 CLR的执行模型——一个Hello World的故事

    好吧,废话少说,先上一章Hello World图: 我们有了一个Hello world程序,如此之简单,再加上我今天没有用汉字编程o(>﹏<)o,所以一切很简单明了. 故事开始: 编译: ...

  5. 一个update的小故事

    偶尔测试了一段小代码,写个循环 if object_id('tempdb..#TB') is not null drop table #TB go create table #TB ( ID int ...

  6. 第一讲 一个简单的Qt程序分析

    本文概要:通过一个简单的Qt程序来介绍Qt程序编写的基本框架与一些Qt程序中常见的概念 #include <QApplication> #include <QPushButton&g ...

  7. 讲一个使用jquery-slick旋转木马效果插件案例

    效果展示连接 http://www.jqcool.net/demo/201405/jquery-slick/ 今天刚接触这个插件,被这插件搞的大脑风暴了 所以来记录一下使用方法 首先注意一点 不特别标 ...

  8. python如何讲一个文件中的图片分到两个

    最近在做一个图像分类的比赛,作为初次接触深度学习的菜鸟,上手了keras.说实话,除了keras教程,中文博客的技术支持太差了.正在头大的学习中...废话不多说,记录一下学习中的一些小细节.在遇到ge ...

  9. 讲一个linux服务启动报错问题排查

    例子 首先我们在/usr/lib/systemd/system目录下创建一个服务文件,写下服务启动任务配置.下面我以prometheus的node_exporter为例 vim /usr/lib/sy ...

随机推荐

  1. C#“必须先将当前线程设置为单个线程单元(STA)模式方可进行OLE调用”异常解决方案

    关于这类问题网上搜索会有很多解决方案,但基本的意思都相差不大,大致问题出于启用线程时调用类似剪贴板Clipboard.SetDataObject出错,我把我的测试代码展现下: 解决方案:只需将thre ...

  2. Orchard详解--第八篇 拓展模块及引用的预处理

    从上一篇可以看出Orchard在处理拓展模块时主要有两个组件,一个是Folder另一个是Loader,前者用于搜索后者用于加载. 其中Folder一共有三个:Module Folder.Core Fo ...

  3. Python操作字典(dict)

    一.字典定义 >>> dict={} 二.字典元素添加 >>> dict['性别']='男' >>> dict {'性别': '男'} >& ...

  4. python——函数之装饰器

    1 问题 实际生活中,我们很难一次性就把一个函数代码写得完美无缺.当我们需要对以前的函数添加新功能时,我们应该怎么做? 2 问题解决思路 (1)可以直接修改原来的函数,在函数内直接修改.当我们对多个函 ...

  5. February 11th, 2018 Week 7th Sunday

    Grasp all, lose all. 欲尽得,必尽失. Not to be greedy and not to try to get everything. Our time, energy an ...

  6. C语言 求两数的最大公约数和最小公倍数

    //作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ #include<stdio.h> //最大公约数 int gys(int x,int ...

  7. 让python bottle框架支持jquery ajax的RESTful风格的PUT和DELETE等请求(新方法)

    通过上篇博文的方法处理后,进入代码调试后发现ajax获取不了服务器端返回的数据,度娘后发现原来AJAX的OPTIONS请求方式是状态类型查询,即向服务器提交信息后不返回任何信息,只将执行状态(200状 ...

  8. Python 简易版选课系统

    一.创建学生类 # # 创建学生类 import random class Student: def __init__(self,num,name,address,course_lst=None): ...

  9. 深入理解Ribbon之源码解析

    什么是Ribbon Ribbon是Netflix公司开源的一个负载均衡的项目,它属于上述的第二种,是一个客户端负载均衡器,运行在客户端上.它是一个经过了云端测试的IPC库,可以很好地控制HTTP和TC ...

  10. 让你提前认识软件开发(21):C程序中的定时器

    版权声明:本文为博主原创文章.对文章内容有不论什么意见或建议.欢迎与作者单独交流.作者QQ(微信):245924426. https://blog.csdn.net/zhouzxi/article/d ...