paxos协议更新日志
基于Paxos协议的数据同步与传统主备方式最大的区别在与Paxos只需任意超过半数的副本在线且相互通信正常,就可以保证服务的持续可用,且数据不丢失。
Basic paxos协议更新日志
我们将数据持久化的需求抽象为:在N个server的机群上,持久化数据库或者文件系统的操作日志,并且为每条日志分配连续递增的logID,我们允许多个客户端并发的向机群内的任意机器发送日志同步请求。
将每条日志的持久化流程都看作一个“Paxos Instance”,不同的logID代表不同的Paxos Instance形成的“决议(decision)”。即每一个logID标识着一轮完整paxos协议流程的执行,最后形成decision。机群内的每个server同时作为paxos的acceptor和proposer。
获取LogID
Server收到客户端的持久化日志请求后,因此向所有acceptor查询它们本地目前已写盘的最大logID,而只需收集到majority返回的结果,并选择其中最大的logID+1作为本次待持久化日志的logID。
从上面的描述可以看出,这里并不能保证并发提交的两条日志一定被分配到不同的logID,而是依靠后续的paxos协议流程来达到对一个logID形成唯一的decision的目的。
产生ProposalID
这里我们使用server的timestamp联合ip作为proposalID,其中timestamp在高位,ip在低位。(为了唯一卫衣proposalID,只要要求时钟的误差范围小于server重启的时间)
Prepare阶段
只有在这个Paxos Instance内(即针对这个logID)没有response过proposalID大于等于当前proposal的,并且也没有“接受(accept)”过proposalID大于当前proposal的,才可以response,并承诺不再accept那些proposalID小于当前proposal的。
上面Prepare阶段的处理流程暗示,对于分配到相同logID的不同日志,由于他们的proposalID不同,acceptor在response一个较小proposalID后,是允许继续response后来的较大的proposalID的。
Accept请求阶段
如果majority的response中的日志内容都为空,那么可以向所有acceptor发出accept request并携带上当前日志内容;而如果有任意的response中的日志内容有效,那么说明当前logID已经别其他日志占用,因此需要回退,回到第一步“获取logID”重新执行。
Accept执行阶段
而如果ProposalID小于当前最大minProposal的,则说明有logID切proposalID更大的proposal在并发执行,当前proposal会被覆盖,因此回复proposer要求回退到第一步“获取logID”重新执行。
这里的流程暗示,针对一个logID,如果之前已经有日志内容持久化成功,那么这条日志一定会被选为accept request;而如果之前日志内容仅仅在小于半数的server上写到磁盘,那么最终这条logID的内容有可能是有效日志,也有可能内容为空。(本例中可能两个提议者竞争一个logID,然后本例中为了加快收敛,其中一个自动放弃,选择更大的logID)
日志内容读取
在读取的时候也需要回放一遍paxos协议,防止读到未提交的日志(相当于raft的提交阶段?)。
为什么需要comfirm日志
假设有a, b, c 3个节点, 刚开始的时候, 3个节点的值是一致的, 都是v1. 这时候一个proposer发起一轮paxos请求, 希望将值设置成v2. 那么可能出现两种情况, 一种是paxos成功了, a, b, c的多数派中value设置成了v2, 也就是说v2被批准了(假设a, b, c的值分别是v1, v2, v2). 另外一种是失败了, a, b, c的多数派中value仍然是v1, 也就是说v2没有被批准, 但是a, b, c中可能存在少数派节点的值是v2(假设a, b, c的值分别是v1, v1, v2). 按照p2a的流程, 选取proposal的原则是选取多数派中, proposal号最大的作为期望被批准的value. 在上述两种情况下, 当reader读取数据时, 按照p2a的逻辑, 既可能读到v1, 也可能读到v2, 那这样的话, 如果有一个acceptor故障了, 其实reader就无法准确知道之前被批准的value了吧? 我看paxos made simple的论文中也提到, 如果有一个acceptor故障了, 也不可能找出被批准的value了, 唯一的办法就是issue a proposal, 然后运行一轮新的paxos算法了。这是不是说, 不管reader读到的是v1还是v2, 仍然发起一轮paxos协议, 保证一致性就ok了
简而言之,就是只有leader某条日志才知道某条日志复制到大多数,而参与者并不知道。所以在提交的时候,要么再跑一次paxos,要么写一条comfirm日志
Multi-paxos更新日志
Leader的产生
通过Multi-paxos,我们可以简化掉产生logID阶段和prepare阶段,而是由唯一的leader产生logID,然后直接执行accept,得到多数派确认即表示redolog同步成功。
首先,需要明确的是Multi-Paxos协议并不假设全局必须只能有唯一的leader来生成日志,它允许有多个“自认为是leader的server”来并发生成日志,这样的场景即退化为Basic-Paxos。
Leader产生并不是走完一个完整的basic paxos流程,而是只走了proposal prepare阶段,所以可能同时产生多个leader。因此,我们需要先写一条StartWorking日志,成功写下这条日志升级为唯一leader
confirm日志优化
因为在读取日志的时候,需要再进行一次basic paxos协议。因此引入confirm日志,针对刚刚提交的日志写入一条confirm日志。出于性能考虑,实际操作中,批量发送confirm日志,因此,读到未确认的日志,还是需要走一遍paxos协议
新任leader对日志的重确认
新任leader可能保存的日志落后于前任leader,因此需要对小于当前集群中max log id的日志都进行,只要大多数回复max log id即可。这样的结果可能超越了前任已经accept的日志记录,称为最大commit原则。
“幽灵复现”日志的处理
使用Paxos协议处理日志的备份与恢复,可以保证确认形成多数派的日志不丢失,但是无法避免一种被称为“幽灵复现”的现象,如下图所示:
x | Leader | A | B | C |
---|---|---|---|---|
第一轮 | A | 1-10 | 1-5 | 1-5 |
第二轮 | B | 宕机 | 1-6,20 | 1-6,20 |
第三轮 | A | 1-20 | 1-20 | 1-20 |
第一轮中A被选为Leader,写下了1-10号日志,其中1-5号日志形成了多数派,并且已给客户端应答,而对于6-10号日志,客户端超时未能得到应答。
第二轮,A宕机,B被选为Leader,由于B和C的最大的logID都是5,因此B不会去重确认6-10号日志,而是从6开始写新的日志,此时如果客户端来查询的话,是查询不到6-10号日志内容的,此后第二轮又写入了6-20号日志,但是只有6号和20号日志在多数派上持久化成功。
第三轮,A又被选为Leader,从多数派中可以得到最大logID为20,因此要将7-20号日志执行重确认,其中就包括了A上的7-10号日志,之后客户端再来查询的话,会发现上次查询不到的7-10号日志又像幽灵一样重新出现了。
对于将Paxos协议应用在数据库日志同步场景的情况,“幽灵复现”问题是不可接受,一个简单的例子就是转账场景,用户转账时如果返回结果超时,那么往往会查询一下转账是否成功,来决定是否重试一下。如果第一次查询转账结果时,发现未生效而重试,而转账事务日志作为幽灵复现日志重新出现的话,就造成了用户重复转账。
为了处理“幽灵复现”问题,我们在每条日志的内容中保存一个generateID,leader在生成这条日志时以当前的leader ProposalID作为generateID。按logID顺序回放日志时,因为leader在开始服务之前
一定会写一条StartWorking日志(先同步再写StarWorking日志),所以如果出现generateID相对前一条日志变小的情况,说明这是一条“幽灵复现”日志(它的generateID会小于StartWorking日志),要忽略掉这条日志。
其中,log1和log6分别是第一轮和第二轮的start working log。
本质上是通过在发生leader权抢占的时候,ProposalID的递增性质保证了不会回放以前的logID。
multi-paxos和raft对比
以下是我自己的观点,不保证正确性
- raft logID递增,multi_paxos并不需要
- multi_paxos为了保证读到的日志已经提交,需要再走一边paxos确认日志;raft每次获得多数派的认可后,也需要向参与者发送提交命令(相当于读取命令)。
- 因为multi-paxos的logID不连续,在leader权抢占的时候,所以有了最大commit原则,最大commit原则可能产生幽灵日志,如果epochID小于上一条,就不回放,所以有了不回放上一个任期的日志。
paxos协议更新日志的更多相关文章
- Paxos协议理解
第三次报告: 理解Paxos协议 一. Paxos协议背景 什么是Paxos协议? 一般地,从客户端和服务器的角度,任何一个分布式系统都可以理解成由一个服务器集合和一个客户端集合组成,一个或多个客户端 ...
- Easy Sysprep更新日志-skyfree大神
Easy Sysprep更新日志: Skyfree 发表于 2016-1-22 13:55:55 https://www.itsk.com/forum.php?mod=viewthread&t ...
- Paxos协议超级详细解释+简单实例
转载自: https://blog.csdn.net/cnh294141800/article/details/53768464 Paxos协议超级详细解释+简单实例 Basic-Paxos算法 ...
- Paxos协议笔记
对Paxos协议的介绍,可以通过Leslie Lamport的<Paxos Made Simple>展开学习和了解.Paxos算法在允许失败的分布式系统环境下,实现系统一致性.失败的情况有 ...
- [实战]MVC5+EF6+MySql企业网盘实战(29)——更新日志
摘要 NetDisk更新日志,及项目使用说明. 开发工具 Vs2013+mysql+ef6+mvc5 bug 1.在加载列表的时候,默认加载的所有,修改为,过滤逻辑删除的文件. 2.加载音乐,文档等分 ...
- AgileEAS.NET SOA中间件平台更新日志 2015-04-28
一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...
- python解析git log后生成页面显示git更新日志信息
使用git log可以查到git上项目的更新日志. 如下两个git项目,我想把git的日志信息解析成一个便于在浏览器上查看的页面. https://github.com/gityf/lua https ...
- 更新日志 - fir.im「高级统计」功能上线
距离 2016 年到来只剩 10 个日夜,fir.im 也准备了一些新鲜的东西,比如「高级统计」功能和「跳转应用商店」功能,帮助你更好地管理.优化应用,欢迎大家试用反馈:) 新增高级统计功能 这次更新 ...
- 更新日志 - fir.im Jenkins & Gradle 插件上线
最近 fir.im 工程师们效率爆表,fir.im 实用工具集合又添加了新的成员-- Jenkins & Gradle 插件,让 App 打包上传更加简单快速. fir.im Jenkins ...
随机推荐
- 转一篇做BI项目的好文
首先,我们有一个大的假设前提,集团报表平台是服务于大型公司,比如有很多分公司,子公司,多部门等,并且有BI需求的访问人群超过1000以上的公司. 这样,我们的关键词是:集团 平台 运营 集团:意味着, ...
- PHP 生成16 uuid
从c# 翻译而来 <?php $i=1; $guidStr=string_make_guid(); echo $guidStr."\n"; $byte_array = unp ...
- [微信开发] 微信网页授权Java实现
功能:主要用于在用户通过手机端微信访问第三方H5页面时获取用户的身份信息(openId,昵称,头像,所在地等..)可用来实现微信登录.微信账号绑定.用户身份鉴权等功能. 开发前的准备: 1.需 ...
- Dalsa线扫相机SDK开发-小试牛刀(1)
拿到了dalsa相机,可以用Sapera软件配置相机,进行图像采集.但是自己开发的话就得撸起袖子写代码了,查了两篇不错的博文,作为指导. Sapera帮助文档 - <好好先生>专栏 - 博 ...
- [ASP.NET].NET逻辑分层架构总结
一.基础知识准备: 1.层的原则: (1)每一层以接口方式供上层调用. (2)上层只能调用下层. (3)依赖分为松散交互和严格交互两种. 2.业务逻辑分类: (1)应用逻辑. (2)领域逻辑. 3.采 ...
- 深入理解Aspnet Core之Identity(3)
主题 账户管理一个比较常见的功能就是密码强度策略,Identity已经内置了一个通用的可配置的策略,我们一般情况下可以直接拿来用即可.本篇我会介绍一些Identity内置的密码策略类:Password ...
- mysql之使用centos7实现主从复制(读写分离)的实现过程
什么是主从复制? 主从复制,是用来建立一个和主数据库完全一样的数据库环境,称为从数据库:主数据库一般是准实时的业务数据库. 主从复制的作用(好处)! 1.做数据的热备,作为后备数据库,主数据库服务器故 ...
- C# 实现图片压缩
代码: private static ImageCodecInfo GetImageCodecInfo(ImageFormat imageFormat) { ImageCodecInfo[] imag ...
- 【cocos2d-x 手游研发----精灵的八面玲珑】
继续上一篇文章继续聊吧,这章内容会比较多,也会附上代码,很多朋友加了群,大家在群里面探讨了很多东西,这让大家都觉得受益匪浅,这便是极好的,废话不多了,精灵是游戏的重要组成部分,那ARPG里面的精灵必然 ...
- 用navicat远程连接mysql:Can't connect to MySQL server (10060)
出现这种现象的原因有两个,一个是当前用户被mysql服务器拒绝,另外一个原因是3306端口被被防火墙禁掉,无法连接到该端口.解决方法如下: 1.设置远程用户访问权限: // 任何远程主机都可以访问数据 ...