使用multi-paxos实现日志同步应用
paxos
说multi-paxos之前先简要说一下paxos
paxos是在多个成员之间对某个值(提议)达成一致的一致性协议。这个值可以是任何东西。比如多个成员之间进行选主,那么这个值就是主的身份。在把multi-paxos协议应用在日志同步中时,这个值就是一条日志。网上讲paxos的文章已经很多了,这里简要说明一下。
paxos分为prepare和accept两个阶段。协议中有两个主要的角色,proposer和acceptor。
value被majority accept之前,每个acceptor可以accept多个不同的值。但是,一旦一个value被majority accept(即value达成一致),那么这个value就不会变了。因为prepare阶段会将该value给找出来,随后accept阶段会使用这个value,后续的所有的提案都会选择这个value。
需要注意的是,每个阶段都是收到majority的响应后即开始处理。并且由于机器会宕机,acceptor需要对acceptedProposalID, acceptedValue和minProposal进行持久化。
从流程中可以看出prepare有两个作用:
- 大的proposal id会block未完成的小的proposal id达成一致的过程,所以为了减少无效的prepare请求,每次都选择比自己以往见过的proposal id更大的id。
- 一旦某个value达成一致,那么后续的prepare都会找到这个value作为accept阶段的值
可以看出,一次paxos达成一致至少需要两次网络交互。
multi-paxos
paxos是对一个值达成一致,multi-paxos是运行多个paxos instance来对多个值达成一致,每个paxos instance对一个值达成一致。在一个支持多写并且强一致性的系统中,每个节点都可以接收客户端的写请求,生成redo日志然后开始一个paxos instance的prepare和accept过程。这里的问题是每条redo日志到底对应哪个paxos instance。
在日志同步应用中,用log id来区分不同的paxos instance。每条日志都由一个id唯一标示,这个log id标识一个paxos instance,这个paxos instance达成一致,即对应的日志内容达成一致,即majority的成员accept了这个日志内容。在一个由N个机器(每个机器既承担proposer也承担acceptor角色)组成的集群(通常叫做paxos group)中,每个proposer都可以产生redo日志并且进行paxos instance,那么每条redo日志到底使用哪个log id? 显然,每个proposer都会选择自己知道的还没有达成一致的最小的log id来作为这次日志的log id,然后运行paxos协议,显然,多个proposer可能会选择同一个log id(最典型的场景就是空集群启动的情况下),最终,只有一个proposer能够成功,那么其他的proposer就需要选择更大的未达成一致的log id来运行paxos。显然,这种冲突是非常严重的,会有很多的proposer成功不了进而选择更大的log id来运行paxos。
在真实的系统中,比如chubby, spanner,都会在paxos group中选择一个成员作为leader,只有leader能够propose日志,这样,prepare阶段就不会存在冲突,相当于对整个log文件做了一次prepare,后面这些日志都可以选用同一个proposal id。这样的话,每条日志只需要一次网络交互就能达成一致。回顾一下文章开头提到paxos中需要每个成员需要记录3个值,minProposal,acceptedProposal,acceptedValue,其中后面两个值可以直接记录在log中,而第一个值minProposal可以单独存在一个文件中。由于这里后面的日志都可以选用同一个proposal id,显然,在大部分时间内,minProposal都不需要改变。这正是multi-paxos的精髓
选主
对于paxos来说,主的身份无所谓,主不需要像raft那样拥有最全的已经commit的日志。所以选主算法无所谓,比如大家都给机器ip最大的机器投票,或者给日志最多的投票,或者干脆直接运行一次paxos,值的内容就是主的身份。显然,由于对新主的身份无限制,那么,新主很有可能没有某些已经达成一致的日志,这个时候,就需要将这些已达成一致的日志拉过来,另外,新主也有可能没有某些还未达成一致的日志。如下图所示:
图中,恢复之前,log id等于3的日志C已经在多数派上达成了一致,但是在新主上没有。比如log id等于4的日志D在多数派上没有达成一致,在新主上也没有。
恢复
新主向所有成员发送查询最大log id的请求,收到majority的响应后,选择最大的log id作为日志恢复的结束点。图中,如果收到的majority不包括2号成员,那么log id=6为恢复结束点。如果收到的majority包括2号成员,那么log id=7为恢复结束点。这里取majority的意义在于恢复结束点包含任何的majority达成一致的日志。拿到log id后,从头开始扫描日志,对于每条日志都运行paxos协议确认一次:如果日志之前已经达成一致了,比如日志A,B,C,E,F,那么再次运行paxos的prepare阶段会把日志内容找出来作为accept阶段的值,不影响结果。如果日志之前并没有达成一致,比如日志D,那么当返回的majority中包含3号成员时,D会被选出来当作accept阶段的值,当返回的majority中不包含3号成员时,那么D实际上不会被选出,这时主可以选择一个dummy日志作为accept阶段的值。
恢复优化
可以看出,如果日志非常多,每次重启后都要对每条日志做一次paxos,那么恢复时间可想而知。在上面的例子中,A,B,E已经达成一致,做了无用功。paxos协议中,只有主即proposer知道哪些日志达成了一致,acceptor不知道,那么很容易想到的一个优化就是proposer将已经达成一致的日志id告诉其他acceptor,acceptor写一条确认日志到日志文件中。后续重启的时候,扫描本地日志只要发现对应的确认日志就知道这条日志已经达成多数派,不需要重新使用paxos进行确认了。这种做法有一个问题,考虑如下场景:
旧主成功的给自己和2号成员发送了确认日志,但是没有给3号成员发送成功旧挂了,然后2号成员被选为新主,那么新主不会对log id=3的日志重新运行paxos,因为本机已经存在确认日志。这样的话,3号成员就回放log id=3的日志到上层了。解决这个问题的做法就是followers需要主动的向主询问日志到底有没有达成一致,如果有,则自己补充确认日志。
回放
宕机重启后,对未达成一致的日志重新运行paxos时,如log id=4的日志,如果返回的majority中不包含3号成员,那么日志D不会被找出来,这样就需要将3号成员的log id=4日志置未一条无操作的日志记作NOP日志,D最终也就不会形成多数派。由于multi-paxos允许日志乱序接收,并且日志的长度几乎都不一样,所以在磁盘上log id是乱序的,所以从物理上说,每个成员的日志不是一模一样的。那么要把log id=4的日志覆盖写成NOP日志也就比较麻烦,需要为每条日志维护索引。实现上可以不覆盖写,直接append一条log id=4的NOP日志到日志文件,这样没有问题,因为回放的时候只会回放能找到确认日志的日志到上层应用中。
成员变更
multi-paxos处理成员变更比较简单,规定第i条日志参与paxos同步的时候,其成员组是第i-k条日志包含的成员组(每条日志里面都包含成员组)。
multi-paxos协议之外
multi-paxos只是保证大家对日志达成一致。但是具体multi-paxos运用到真实的系统中时,从应用层面上看,可能会出现一些诡异的问题。考虑如下场景:
如图,1号主写了A,B,C,D,其中B,C,D没有形成多数派,然后A宕机了,2号被选为了主,客户端过来读不到B,C,D,然后B没写任何东西,就挂了,这个时候,A起来后重新被选为主,对B,C,D重新运行paxos,把B,C,D达成了一致,这个时候客户端再次过来读,又能读到B,C,D了。对于multi-paxos本身来说,并没有什么不对的地方,但是上层应用的语义出现了问题:曾经读不到的东西,什么都没做,又能读到了。
解决这个问题的方法是通过主提供服务之前必须成功写入一条start working日志来解决。如下图:
如图,每个成员成为主提供服务之前都要首先写一条start working日志,只有达成多数派才能提供服务。1号在重新成为主之后,通过对log id=2的日志运行paxos,将2号start日志恢复了出来,然后对C和D运行paxos恢复出来后,后续回放的时候,如果发现后面日志中带有的timestamp(其实时leader上任时间)比start working带有的timestamp更小,那么就不回放到上层。随后客户端来读仍然读不到B,C,D,前后保持一致。
使用multi-paxos实现日志同步应用的更多相关文章
- Paxos 实现日志复制同步
Paxos 实现日志复制同步 本篇文章以 John Ousterhout(斯坦福大学教授) 和 Diego Ongaro(斯坦福大学获得博士学位,Raft算法发明人) 在 Youtube 上的讲解视频 ...
- Paxos 实现日志复制同步(Multi-Paxos)
Paxos 实现日志复制同步 这篇文章以一种易于理解的方式来解释 Multi-Paxos 的机制. Multi-Paxos 的是为了创建日志复制 一种实现方式是用一组基础 Paxos 实例,每条记录都 ...
- Paxos 实现日志复制同步(Basic Paxos)
Paxos 实现日志复制同步 本篇文章以 John Ousterhout(斯坦福大学教授) 和 Diego Ongaro(斯坦福大学获得博士学位,Raft算法发明人) 在 Youtube 上的讲解视频 ...
- 从 Basic Paxos 到 Multi Paxos 到 Raft
在朴素Paxos算法中, 各个节点经过 Prepare 和 Accept 阶段, 会达成一个值, 这个值一旦达成, 就不能被修改, 如下例子: 图示1 上面的操作几乎没有任何实用价值, 于是演变成下面 ...
- Multi-Paxos协议日志同步应用
使用Multi-Paxos协议的日志同步与恢复 基于Basic-Paxos协议的日志同步方案, 所有成员的身份都是平等的, 任何成员都可以提出日志持久化的提案, 并且尝试在成员组中进行持久化. 而在实 ...
- Basic-Paxos协议日志同步应用
使用Basic-Paxos协议的日志同步与恢复 传统数据库保持服务持续可用通常采用1主N备, 既采取两种日志同步模式: Maximum Availability和Maximum Protection. ...
- kafka日志同步至elasticsearch和kibana展示
kafka日志同步至elasticsearch和kibana展示 一 kafka consumer准备 前面的章节进行了分布式job的自动计算的概念讲解以及实践.上次分布式日志说过日志写进kafka, ...
- Multi Paxos
Multi Paxos [2] 通过basic paxos 以上步骤分布式系统已经能确定一个值,“只确定一个值有什么用?这可解决不了我面临的问题.” 你心中可能有这样的疑问. 原simple paxo ...
- cdnbest如何查看站点操作日志(同步日志)
1. 在区域列表点同步日志 2. 点击进入后,可以查看对哪个站点进行了操作,操作时间,ip,id都有记录 3. 想知道详细操作了什么内容把鼠标指向操作类型,就会弹出操作的信息
随机推荐
- Android APK如何签名
Android项目以它的包名作为唯一标识,如果在同一设备上安装两个相同的应用,后面安装的应用就会覆盖前面安装的应用.为了避免这种情况的发生,我们需要对作为产品发布的应用进行签名. 签名其实有两个作用: ...
- 《selenium2 Java 自动化测试实战(第二版)》 更新2016.5.3
java 版来了!! 本文档在<selenium2 Python 自动化测试实战>的基础上,将代码与实例替换为java ,当然,部分章节有变更.这主要更语言本身的特点有关.集合和java下 ...
- iOS-掌握了时间就掌握了一切!
Demo下载地址 一. NSDate相关知识 1.获取当前时间 [NSDate date]; 注意: 获取的当前时间是世界时间:比我们用的时间慢8个小时. 2.世界时间转化为本地时间 - (void) ...
- OpenCV2:等间隔采样和局部均值的图像缩小
图像的缩小从物理意义上来说,就是将图像的每个像素的大小缩小相应的倍数.但是,改变像素的物理尺寸显然不是那么容易的,从数字图像处理的角度来看,图像的缩小实际就是通过减少像素个数来实现的.显而易见的,减少 ...
- 在Visual Studio 2012中使用VMSDK开发领域特定语言(一)
前言 本专题主要介绍在Visual Studio 2012中使用Visualization & Modeling SDK进行领域特定语言(DSL)的开发,包括两个部分的内容.在第一部分中,将对 ...
- C# 委托应用总结
一.什么是委托 1.1官方解释 委托是一种定义方法签名的类型.当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联.您可以通过委托实例调用方法. 1.2个人理解 委托就是执行方法(函数)的一个 ...
- ASP.NET MVC对WebAPI接口操作(添加,更新和删除)
昨天<怎样操作WebAPI接口(显示数据)>http://www.cnblogs.com/insus/p/5670401.html 既有使用jQuery,也有使作HttpClient来从数 ...
- 让服务器iis支持.apk文件下载的设置方法
随着智能手机的普及,越来越多的人使用手机上网,很多网站也应手机上网的需要推出了网站客户端,.apk文件就是安卓(Android)的应用程序后缀名,默认情况下,使用IIS作为Web服务器的无法下载此文件 ...
- iOS面试用到的一些知识点和技术
1.APP的生命周期和viewcontroler的生命周期? 答:APP的生命周期:在APP的代理中分为七个阶段: 1.将要启动 2.已经启动 3.将要进入非活动状态 4.进入后台 5.从后台进入前台 ...
- patch 打补丁,和diff 生成制作补丁
一.diff 命令: diff命令就是比较两个文件的差异,然后生成差异文件,即补丁文件. 参数:diff --help获得,最常用的 1.-N --new-file 在比较时,如果没有就拿一个空的文件 ...