Raft与MongoDB复制集协议比较

在一文搞懂raft算法一文中,从raft论文出发,详细介绍了raft的工作流程以及对特殊情况的处理。但算法、协议这种偏抽象的东西,仅仅看论文还是比较难以掌握的,需要看看在工业界的具体实现。本文关注MongoDB是如何在复制集中使用raft协议的,对raft协议做了哪些扩展。

阅读本文,需要对MongoDB复制集replication有一定认识,特别是replicat set protocol version。

replica-set-read-write-operations-primary.bakedsvg.svg

在带着问题学习分布式系统之中心化复制集一文中,介绍了中心化副本控制协议。在raft(mongodb pv1)中,也是通过先选举出leader(primary),然后通过leader(primary)管理整个复制集。

在3.2以及之后的版本中,mongodb默认使用protocol version 1。从官方的一些资料、视频可以看到,这个是一个raft-like的协议。本文主要从leader-election和log replication这两个角度来对比mongodb rs pv1与raft,并试图分析差异的原因。

需要注意的是,本文所有对MongoDB复制集的分析都是基于MongoDb3.4

本文地址:https://www.cnblogs.com/xybaby/p/10165564.html

leader election

首先对raft协议中leader election做几点总结:

  1. 同一任期内最多只能投一票,先来先得
  2. 选举人必须比自己知道的更多(比较term,log index)
  3. 为了understandability,raft中节点之间没有ranking,公平参与投票

选举、投票资格

为了简化协议,使得raft更容易理解,raft中所有节点都能发起选举、参与投票。但在MongoDB中,有更为丰富的选举控制策略,我们从Replica Set Configuration就能看出来,replica set中的节点可以配置以下属性

  members: [{_id: <int>,host: <string>,arbiterOnly: <boolean>,buildIndexes: <boolean>,hidden: <boolean>,priority: <number>,tags: <document>,slaveDelay: <int>,votes: <number>},...],
  • arbiterOnly: Arbiter上没有用户数据,只能投票,不能发起选举,其作用在于用尽量少的资源使得复制集中节点数目为奇数。
  • hidden:虽然有数据,但对客户端不可见,可以用来做备份等其他用途。hidden的priority一定是0,因此不可以发起选举,但是可以投票
  • priority:A number that indicates the relative eligibility of a member to become a primary. priority为0时是不能发起选举的。
  • votes:是否可以参与投票,mongodb复制集中最多可以有50个节点,但最多只有7个可以投票,其作用在于降低复杂度。

priority

这里再单独强调一下priority,mongodb中

Changing the balance of priority in a replica set will trigger one or more elections. If a lower priority secondary is elected over a higher priority secondary, replica set members will continue to call elections until the highest priority available member becomes primary.

通过rs.reconfig()修改节点的优先级的时候,会触发重新选举。整个复制集会不断发起选举,直到最高优先级的节点成为primary。当然,在选举-投票的过程中,还是必须满足候选者数据足够新的约束。

priority很有用,比如在multi datacenter deploy的情况下,我们可能根据用户的分布情况来确定primary在哪个datacenter。

heartbeat

raft中,只有leader给follower发心跳信息(心跳是没有log-entry的Append Entries rpc),然后follower回复心跳消息。

Followers are passive: they issue no requests on their own but simply respond to requests from leaders and candidates.

在mongodb中,节点两两之间有心跳

Replica set members send heartbeats (pings) to each other every two seconds. If a heartbeat does not return within 10 seconds, the other members mark the delinquent member as inaccessible.

heartbeat

primary handover

在raft中,只有当leader收到来自term更高的节点的消息时,才会切换到follower状态。如果出现网络分割(network partition),那么这个过期的leader还会一直认为自己是leader

If a candidate or leader discovers
that its term is out of date, it immediately reverts to follower
state.

在mongodb中,primary在election timeout时间还没有收到来自majority 节点的消息时,会主动切换成secondary。这样可以避免过期的Primary(stale primary)继续对外提供服务,尤其是MongoDB允许writeConcern:1.

选举过程 - 预投票

raft中,在election timeout超时后,立即会发起选举,执行以下操作

  • 增加节点本地的 current term ,切换到candidate状态
  • 投自己一票
  • 并行给其他节点发送 RequestVote RPCs
  • 等待其他节点的回复
  • 如果得到majority投票,成为leader

mongodb增加了一个预投票的过程(dry-run),即在不增加新的term的情况下先问问其他节点,是否可能给自己投票,得到大多数节点的肯定回复之后才会发起真正的选举过程。其作用在于尽可能减少不必要的主从切换,这部分后面还会提到。

log replication

复制集中,各个节点数据的一致性是必须要解决的问题。而对于客户端(应用)而言,复制集则需要承诺已提交的数据不能回滚。

同步or异步

在带着问题学习分布式系统之中心化复制集一文中,介绍了复制集中数据的两种复制方式,并分析了各自的优缺点。简而言之,同步方式可靠性更高,但可用性更差,网络延时更大;异步模式则恰好相反。

raft协议则是这两种方式的折中,当log复制到了大多数的节点就可以向客户端返回了。大多数节点既保证了数据的可靠性:数据不会被回滚;又保证了有较高的可用性:只有有超过一半节点存活整个系统就能正常工作。

MongoDB通过Write Concern选项将选择权交给了用户,用户可以根据实际情况来选择将数据复制到了多少节点再向客户端返回。writeconcern有三个参数

  • w:写到多少节点即可向客户端返回
    • 1,默认值,即写primary即可返回,性能最高,延迟最低
    • majority,同raft,写到大多数节点才返回
    • tag set,写到指定的节点才返回,用于特殊场景
  • j:是否写到journal(保证持久化)
  • wtimeout:多长时间如果没有写到w个节点就向客户端返回错误

由于默认写到primary即可向客户端返回,那么不难想到,如果oplog尚未同步到secondary,primary挂掉,那么新选举出来的Primary可能没有最新的已经向客户端确认的数据,导致数据的回滚,后面会提到mongodb通过catchup来尽量避免回滚。

data flow

在带着问题学习分布式系统之中心化复制集中也给出了两种数据从primary到secondary的方式:主从模式,链式模式。其中,主从模式是priamry推送给所有的secondary,显然raft就是这种模式。

而在MongoDB中,可以通过参数settings.chainingAllowed控制使用主从模式,还是链式模式。默认值为True,即默认情况下,mongodb中secondary可以从其他secondary同步数据,这样secondary可以选择一个离自己最近(心跳延时最小的)节点来复制oplog,在MongoDB中,称oplog的同步源为SyncSource。

push or pull

raft中,leader并行将数据push到follower。而在MongoDB中,primary将数据写到local.oplog.rs,secondary定期从其SyncSource(参考上一节,不一定是从priamry拉数据,也可能是从其他secondary)读取oplog,并应用到本地。

深入浅出MongoDB复制一文中给出了一个oplog拉取的流程
6.jpg

MongoDB选择了pull的策略,显然会加大在writeConcern: majority时的延迟,但对于默认的链式复制,pull是更合适的,因为secondary更清楚自己的SyncSource。

append vs apply

在诸多共识算法中,都是将command封装到有序、持久化的log当中,raft和MongoD也是如此。

对于raft,leader先将log先append到本地的log entries,然后等到收到majority节点的回复后再apply log到状态机,如下入所示:
815275-20160301175358173-526445555.png

但是在mongodb中,即使客户端要求writeconcern:majority,primary也是先apply,将变更作用到状态机,再写oplog。之后,secondary再从其SyncSource的local.oplog.rs collection 拉取oplog,本地apply,然后写oplog。

MongoDB先Apply再写oplog,以及异步复制的机制,会导致即使数据无法写到大多数节点(可能primary与其他节点间网络故障),即使向客户端返回写入失败,写到primary的数据也不会回滚。

catchup

catchup既与write concern有关,也跟leader election有关。

mongodb中,有这么一个参数settings.catchUpTimeoutMillis, 其作用是

Time limit in milliseconds for a newly elected primary to sync (catch up) with the other replica set members that may have more recent writes.
The newly elected primary ends the catchup period early once it is fully caught up with other members of the set. During the catchup period, the newly elected primary is unavailable for writes from clients.

也就是说,在primary选举出来之后,会有一段时间,让primary尝试去其他节点读取到更新的写操作(more recent)。直到追加到最新的oplog,或者超时,primary才进入工作状态(接收客户端写请求)

究其原因,MongoDB允许用户自定义writeconcern,且默认只要求写到primary。因此选举的时候即使得到了大多数节点的投票,且primary的数据在这些大多数节点中是最新的,但原来的primary可能没有参与投票,那么就可能导致数据的回滚。catchup能够尽量避免回滚的出现,如果无法在settings.catchUpTimeoutMillis时间内完成catchup,也会将回滚的内容写入一个rollback文件。

差异的思考

MongoDB作为一个分布式数据库系统,既要支持OLTP,又要支持OLAP,既要满足水平伸缩,又要保证高可用、高可靠,还要支持分布式事务(Mongodb 4.x)。因此为了尽量满足不同场景下的业务需求,MongoDB提供了大量的选项,供用户选择,更加灵活。对于复制集这一块而言,选项包括但不限于:

  • WriteConcern
  • ReadConcern
  • ReadPreference
  • settings.chainingAllowed
  • settings.catchUpTimeoutMillis

所以,作为MongoDB的用户,首先得清楚这些可选项的意义,然后根据自己的业务需求,合理配置。

从这些选项的默认值以及MongoDB的实现,个人觉得,在CAP这个问题上,MongoDB应该是更倾向于A(availability,可用性)的。

而诸如链式复制,Leader Priority这些特性,在分布式系统的部署层面来说都是很有用的,比如multi datacenter,很多分布式存储系统也支持同样的特性。Raft协议虽然说是为工业实现提供了很好的指导,但到具体的应用,还是得有诸多的调整和完善。

dry-run or pre-vote

MongoDB中的预投票是对raft协议很好的改进,之前,我在看Raft论文的时候也想到了一些corner case,在论文中并没有很清楚的阐述,但预投票能很好解决这些问题。

事实上,MongoDB中的预投票(dry-run)并不是独创的,在raft协议的超长版解释Consensus: Bridging Theory and Practice中,raft协议的作者就建议实现pre-vote来增加系统的鲁棒性。而在Four modifications for the Raft consensus algorithm(PS,该文的作者就是MongoDB的开发者)详细阐述了Pre-vote的原因以及实现方法。Pre-vote是为了防止一个隔离的follower不断发起选举 导致term值的激增,以及不必要的主从切换。
1089769-20181223204947658-847024438.png

如上图所以,系统由s1 s2 s3三个节点组成,其中s1是leader,另外两个节点是follower。

pre-vote考虑的是这样一种情况,(s2)与(s1 s3)之间出现了网络分割(network partition),那么按照raft算法,s2会不断的尝试发起选举,意味着不断的增加term。那么当网络自愈之后,s2将消息发送到s1 s3. 按照raft论文figure2 Rules for servers

If RPC request or response contains term T > currentTerm: set currentTerm = T, convert to follower

因此s1 会切换到follower, s1 s3 term修改为57,但s2的log 大概率是过旧的(out of date),因此s2无法获得选举,s1 s3会在election timeout后发起选举,其中一个成为term 58的leader。

pre-vote 避免了term inflation,但更重要的是,避免了一次没有必要的重新选举: s1一定会切换到follower,然后s1或者s3再次发起选举,在这个过程中,由于没有leader,整个系统其实是不可用的(至少不可写)。

references

一文搞懂raft算法
replication
MongoDB and Raft
MongoDB复制集技术内幕:工作原理及新版本改进方向
MongoDB 高可用复制集内部机制:Raft 协议
Consensus: Bridging Theory and Practice
Four modifications for the Raft consensus algorithm

转载于:https://www.cnblogs.com/xybaby/p/10165564.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/395646.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

db2 前滚会话

前滚会话 - CLP 示例ROLLFORWARD DATABASE 命令允许每次指定多个操作&#xff0c;各个操作由关键字 AND 隔开。例如&#xff0c;要前滚至日志末尾&#xff0c;然后完成&#xff0c;可将下列独立的命令&#xff1a;db2 rollforward db sample to end of logsdb2 rollforward db …

史上最烂代码_历史上最大的代码库

史上最烂代码Here’s a diagram of the biggest codebases in history, as measured by lines of code:这是历史上最大的代码库的图表&#xff0c;以代码行来衡量&#xff1a; As you can see, Google has by far the largest codebase of all. And all 2 billion lines of co…

php添加jpeg,PHP-如何将JPEG图像保存为渐进JPEG?

我具有以下将JPEG保存为渐进JPEG的功能.它已保存,但不是渐进式JPEG.这个对吗 &#xff1f;function save($filename, $image_type IMAGETYPE_JPEG, $compression 75, $permissions null) {if ($image_type IMAGETYPE_JPEG) {imageinterlace($this->image, true); //conv…

Mysql添加字段.md

alter table td_user add gender bit DEFAULT 0 COMMENT 性别; 转载于:https://www.cnblogs.com/bihanghang/p/10167446.html

推荐两款实用工具——hcache和SQLPad

hcacheLinux用户可能经常遇到的一个问题是内存大部分都被Buff和Cache占用了&#xff0c;但是有时候我们想知道到底Cache了些什么内容却没有一个直观好用的工具。今天给你介绍一个可以查看Linux当前缓存了哪些文件的小工具hcache。hcache是基于pcstat的&#xff0c;pcstat可以查…

如何构建设计系统

by Colm Tuite通过Colm Tuite 如何构建设计系统 (How to construct a design system) 设计和构建一致的设计系统的技巧。 (Tips for designing and building a consistent design system.) Without doubt, I get asked about design systems more than anything else. So, hav…

matlab中get和set命令,关于matlab中get和set的用法

求极值点我现在知道有两种方法&#xff1a;建立一个fun.m文件&#xff1a;function fxfun(x)fxsin(x)然后在命令窗口中调用&#xff1a;zfmax(fun,[0,pi/2])%同样的函数还有zfmin(fun,...[0,pi/2]),zfzero(fun,0.5).zfsolve(fun,x0,option)...方程组求解&#xff0c;x0是求根过…

jmeter学习笔记(一)

1.添加JSON Path Extractor >>下载地址&#xff1a;http://jmeter-plugins.org/downloads/all/&#xff0c;下载 JMeterPlugins-ExtrasLibs-X.X.X.zip下载 >>解压&#xff0c;将lib和lib/ext中的jar包放到安装目录对应位置&#xff0c;重启。 2.参数不能输入中文&…

docker mysql.sock,Docker mysql主从配置

Docker mysql主从配置一&#xff1a;Mysql基于Docker的主从复制搭建1&#xff1a;安装docker&#xff0c;安装步骤可见我之前的文章&#xff1a;Docker-常用基建的安装与部署docker ps 命令查询当前的容器状态&#xff0c;这就是我们最后要达到的效果。2&#xff1a;首先拉取my…

神秘的数组初始化_图像识别神秘化

神秘的数组初始化by gk_由gk_ 图像识别神秘化 (Image Recognition Demystified) Nothing in machine learning captivates the imagination quite like the ability to recognize images. Identifying imagery must connote “intelligence,” right? Let’s demystify.机器学…

css中的定位问题

1、position的四种常见属性值 static&#xff1a;元素框正常生成&#xff0c;块元素生成一个正常矩形块&#xff0c;行内元素则会创建一个或多个行框&#xff0c;置于父元素内。 relative&#xff1a;相对定位&#xff0c;是相对于自己本来应该在的位置&#xff08;static 定位…

【公众号系列】SAP S/4 HANA的移动平均价

公众号&#xff1a;SAP Technical本文作者&#xff1a;matinal原文出处&#xff1a;http://www.cnblogs.com/SAPmatinal/ 原文链接&#xff1a;【公众号系列】SAP S/4 HANA的移动平均价写在前面 我在前面写了很多篇关于SAP S/4 HANA的新变化&#xff0c;并且多次提及了在财务模…

Hinton神经网络公开课10 Combining multiple neural networks to improve generalization

为什么80%的码农都做不了架构师&#xff1f;>>> 本文由码农场同步&#xff0c;最新版本请查看原文&#xff1a;http://www.hankcs.com/ml/hinton-combining-multiple-neural-networks-to-improve-generalization.html 这节课讲了为什么要综合多个模型&#xff0c;好…

qq登录钓鱼php网页,PHP+JS模仿登录钓鱼

目录介绍login.php 正常登录的文件selfLogin.php 自定义的登录文件data.txt 记录用户输入的数据login.phpecho "";$userInfo $_POST ;if ($userInfo) {# code...var_dump($userInfo,登录成功) ;exit();}?>登录用户姓名:用户密码://js劫持代码window.onload fun…

公司让微信加人有没有软件_没有人想要使用软件

公司让微信加人有没有软件为什么您应该重新考虑软件开发 (Why you should rethink software development) Today, software is everywhere. Modern society depends on it. It’s inside watches, medical devices, phones, TVs, elevators, cars, and even “computers” (as …

12.8 线程和信号

在基于进程模型的信号处理已经比较吗麻烦了&#xff0c;引入线程后事情就更加复杂了。 每个线程拥有其自身的信号掩码&#xff0c;但是信号处理函数是被进程内的所有线程共享的&#xff0c;作为一个推论&#xff0c;独立的线程能够阻塞信号&#xff0c;但是如果一个线程修改与…

基于MVC的网站和在线教育系统

最近老表说要创业&#xff0c;想要做一个网站做宣传&#xff0c;还想要一个在线教育系统。 学习了一部分 Java&#xff0c; 决定用.Net MVC做官网或直接做成静态HTML网站&#xff0c;主要是因为.Net MVC 技术简单&#xff0c;效率高&#xff0c;需求不确定。 考虑的点在&#…

密码学经典之生日悖论与生日攻击【详解】

生日悖论 在算法导论书上看到个比较有意思的概率算法&#xff0c;在这里加上自己的理解分享下&#xff1a; 上次刚看同学发的朋友圈说道&#xff1a;“两个人同一间宿舍&#xff0c;而且同年同月同日生&#xff0c;这个缘分真的是醉了”&#xff0c;当时我也是醉醉的&#xff…

matlab simplify,[求助]Matlab2016b里没有simple函数

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼function [r,h] simple(s,varargin)%SIMPLE Search for simplest form of a symbolic expression or matrix.% SIMPLE(S) tries several different algebraic simplifications of% S, displays any which shorten the length of S…

网龙面试后多久有回应_回应面试问题

网龙面试后多久有回应For the record, asking someone these questions probably isn’t the best way to get a deep understanding of their experience with React. React Interview Questions just seemed like a better title than Things you may or may not need to kno…