通俗易懂关于Paxos的直观解释
一、Paxos是什么
在分布式系统中保证多副本数据强一致性算法。
没有paxos的一堆机器, 叫做分布式
有paxos协同的一堆机器, 叫分布式系统
这个世界上只有一种一致性算法,那就是Paxos … - Google Chubby的作者Mike Burrows
其他一致性算法都可以看做Paxos在实现中的变体和扩展,比如raft。
二、先从复制算法说起
防止数据丢失,所以需要数据进行复制备份
2.1 主从异步复制
主节点接到写请求,主节点写本磁盘,主节点应答OK,主节点复制数据到从节点
如果数据在数据复制到从节点之前损坏,数据丢失。
2.2 主从同步复制
主节点接到写请求,主节点复制日志到所有从节点,从节点可能会阻塞,客户端一直等待应答,直到所有从节点返回
一个节点失联导致整个系统不可用,整个可用性的可用性比较低
2.3 主从半同步复制
主接到写请求,主复制日志到从库,从库可能阻塞,如果1~N个从库返回OK,客户端返回OK
可靠性和可用性得到了保障,但是可能任何从库都没有完整数据
2.4 多数派写读
往一个主接节点写入貌似都会出现问题,那我们尝试一下往多个节点写入,舍弃主节点。
客户端写入 W >= N / 2 + 1
个节点, 读需要 W + R > N, R >= N / 2 + 1
,可以容忍 (N - 1)/ 2
个节点损坏
最后一次写入覆盖先前写入,需要一个全局有序时间戳。
多数派写可能会出现什么问题?怎么解决这些问题呢?
三、从多数派到Paxos的推导
假想一个存储系统,满足以下条件:
1. 有三个存储节点 2. 使用多数派写策略 3. 假定只存储一个变量i 4. 变量i的每次更新对应多个版本,i1,i2, i3..... 5. 该存储系统支持三个命令: 1. get 命令,读取最新的变量i,对应多数派读 2. set <n> 命令,设置下版本的变量i的值<n>,直接对应的多数派写 3. inc <n> 命令, 对变量i增加<n>,也生成一个新版本,简单的事务型操作
3.1 inc的实现描述
1. 从多数中读取变量i,i当前版本1
2. 进行计算,i2 = i1 + n,i变更,版本+1
3. 多数派写i2,写入i,当前版本2
4. 获取i,最新版本是2
这种实现方式存在一下问题:
如果2个并发的客户端同时进行inc操作,必然会产生Y客户端覆盖X客户端的问题,从而产生数据更新丢失
假设X,Y两个客户端,X客户端执行命令inc 1,Y客户端执行inc 2,我们期望最终变量i会加3
但是实际上会出现并发冲突
1. X客户端读取到变量i版本1的值是2
2. 同时客户端Y读取到变量i版本1的值也是2
3. X客户端执行i1 + 1 = 3,Y客户端执行i1 + 2 = 4
4. X执行多数派写,变量i版本2的值是2,进行写入(假定X客户端先执行)
5. Y执行多数派写,变量i版本2的值是4,进行写入(如果Y成功,会把X写入的值覆盖掉)
所以Y写入操作必须失败,不能让X写入的值丢失。但是该怎么去做呢?
3.2 解决多数派写入冲突
我们发现,客户端X,Y写入的都是变量i的版本2,那我们是不是可以增加一个约束:
整个系统对变量i的某个版本,只能有一次写入成功。
也就是说,一个值(一个变量的一个版本)被确定(客户端接到OK后)就不允许被修改了。
怎么确定一个值被写入了呢?在X或者Y写之前先做一次多数派读,以便确认是否有其他客户端进程在写了,如果有,则放弃。
客户端X在执行多数派写之前,先执行一个多数派读,在要写入的节点上标识一下客户端X准备进行写入,这样其他客户端执行的时候看到有X进行写入就要放弃。
但是忽略了一个问题,就是客户端Y写之前也会执行多数派读,那么就会演变成X,Y都执行多数派读的时候当时没有客户端在写,然后在相应节点打上自己要写的标识,这样也会出现数据覆盖。
3.3 逐步发现的真相
既然让客户端自己标识会出现数据丢失问题,那我们可以让节点来记住最后一个做过写前读取的进程,并且只允许最后一个完成写前读取的进程进行后续写入,拒绝之前做过写前读取进行的写入权限。
X,Y同时进行写前读取的时候,节点记录最后执行一个执行的客户端,然后只允许最后一个客户端进行写入操作。
使用这个策略变量i的每个版本可以被安全的存储。
然后Leslie Lamport写了一篇论文,并且获得了图灵奖。
四、重新描述一下Paxos的过程(Classic Paxos)
使用2轮RPC来确定一个值,一个值确定之后不能被修改,算法中角色描述:
•Proposer 客户端
•Acceptor 可以理解为存储节点
•Quorum 在99%的场景里都是指多数派, 也就是半数以上的Acceptor
•Round 用来标识一次paxos算法实例, 每个round是2次多数派读写: 算法描述里分别用phase-1和phase-2标识. 同时为了简单和明确, 算法中也规定了每个Proposer都必须生成全局单调递增的round, 这样round既能用来区分先后也能用来区分不同的Proposer(客户端).
4.1 Proposer请求使用的请求
// 阶段一 请求 class RequestPhase1 { int rnd; // 递增的全局唯一的编号,可以区分Proposer }
// 阶段二 请求 class RequestPhase2 { int rnd; // 递增的全局唯一的编号,可以区分Proposer Object v; // 要写入的值 }
4.2 Acceptor 存储使用的应答
// 阶段一 应答 class ResponsePhase1 { int last_rnd; // Acceptor 记住的最后一次写前读取的Proposer,以此来决定那个Proposer可以写入 Object v; // 最后被写入的值 int vrnd; // 跟v是一对,记录了在哪个rnd中v被写入了 }
// 阶段二 应答 class ResponsePhase2 { boolean ok; }
4.3 步骤描述
阶段一
当Acceptor收到phase-1的请求时:
● 如果请求中rnd比Acceptor的last_rnd小,则拒绝请求
● 将请求中的rnd保存到本地的last_rnd. 从此这个Acceptor只接受带有这个last_rnd的phase-2请求。
● 返回应答,带上自己之前的last_rnd和之前已接受的v.
当Proposer收到Acceptor发回的应答:
● 如果应答中的last_rnd大于发出的rnd: 退出.
● 从所有应答中选择vrnd最大的v: 不能改变(可能)已经确定的值,需要把其他节点进行一次补偿
● 如果所有应答的v都是空或者所有节点返回v和vrnd是一致的,可以选择自己要写入v.
● 如果应答不够多数派,退出
阶段二:
Proposer:
发送phase-2,带上rnd和上一步决定的v
Acceptor:
● 拒绝rnd不等于Acceptor的last_rnd的请求
● 将phase-2请求中的v写入本地,记此v为‘已接受的值’
● last_rnd==rnd 保证没有其他Proposer在此过程中写入 过其他值
4.4 例子
无冲突:
有冲突的情况,不会改变写入的值
客户端X写入失败,因此重新进行2轮PRC进行重新写入,相当于做了一次补偿,从而使系统最终一致
五、问题及改进
活锁(Livelock): 多个Proposer并发对1个值运行paxos的时候,可能会互 相覆盖对方的rnd,然后提升自己的rnd再次尝试,然后再次产生冲突,一直无法完成
然后后续演化各种优化:
multi-paxos:用一次rpc为多个paxos实例运行phase-1
fast-paxos:增加quorum的数量来达到一次rpc就能达成一致的目的. 如果fast-paxos没能在一次rpc达成一致, 则要退化到classic paxos.
raft: leader, term,index等等..
六、参考
1. 文章主要来自博客:https://blog.openacid.com/algo/paxos/
2. 一个基于Paxos的KV存储的实现:https://github.com/openacid/paxoskv
3. Paxos论文:https://lamport.azurewebsites.net/pubs/paxos-simple.pdf

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
OLAP进阶之“性能提升”
更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群 在数据处理和分析的领域,提升查询效率始终是一项关键挑战。对于 OLAP 来说,性能的关键需求在于能支持实时分析,应对复杂查询,提供快速响应,并具备良好的可扩展性。这些方面,对于满足高效、准确的数据分析需求至关重要。 火山引擎正式发布《云原生数据仓库ByteHouse性能白皮书》,白皮书通过使用 SSB 100G、TPC-H 100G、TPC-DS 100G 数据集进行性能测试,展示出 ByteHouse 在查询效率方面的显著成果,并详细介绍ByteHouse在实时数仓、复杂查询等八大应用场景的高性能应用表现。 作为一款OLAP引擎,伴随字节跳动各业务的发展,ByteHouse已经过数百个应用场景和数万用户锤炼,在2022年3月,部署规模已超过1万8000台,最大的集群规模在 2400 余个节点,管理总数据量超过700PB,并逐步在外部金融、泛互等场景应用和推广。为了更好支持字节内外部大规模数据和复杂场景应用,性能一直以来是ByteHouse重点打磨的产品基本功。 SSB、TPC-H 和 TPC-DS ...
- 下一篇
MyData v0.8.0 更新日志
MyData 是基于数据资产为核心思想设计和开发的,提供数据集成服务,简化跨系统之间的数据对接,目标是:让用户更好的掌控和管理数据 MyData 是针对多应用之间数据集成的场景,通过 Web API 方式 为开发人员提供更安全、更方便的对接集成; 0.8.0 主要更新内容: 1. 新增通过邮件发送业务数据; 2. 支持字段对比查询; 3. 数据类型增加number; 4. 优化任务整体流程; 具体内容如下: 新功能 任务管理 消费数据类型任务 新增“发送邮件”模式,将符合条件的业务数据导出excel 并发送到指定邮箱; 过滤条件支持字段之间的对比查询; 数据管理 字段类型,增加 数值类型(number),支持浮点型数据 从而不会转为字符串; 集成管理 增加删除业务数据功能,方便调试阶段清理数据; 任务管理 提供数据类型任务的分批参数中,增加“两次获取相同数据即结束任务”的开关 以便控制任务正常结束或异常中止; 优化 任务管理 任务周期 改用Cron编辑器; 过滤条件的字段 改用下拉框,避免填写出错; 日志列表 增加刷新按钮; 当选择发送邮件时,禁用分批模式; 定时任务 优化整体流程逻辑...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS8编译安装MySQL8.0.19
- CentOS6,CentOS7官方镜像安装Oracle11G
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Red5直播服务器,属于Java语言的直播服务器
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7