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,一经查实,立即删除!

相关文章

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

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

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.参数不能输入中文&…

【公众号系列】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;好…

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

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

Bagging与随机森林算法原理小结

在集成学习原理小结中&#xff0c;我们讲到了集成学习有两个流派&#xff0c;一个是boosting派系&#xff0c;它的特点是各个弱学习器之间有依赖关系。另一种是bagging流派&#xff0c;它的特点是各个弱学习器之间没有依赖关系&#xff0c;可以并行拟合。本文就对集成学习中Bag…

iOS:多线程技术GCD的使用

GCD的使用&#xff1a; 1.队列的类型1.1 主队列&#xff1a;mian queue,主线程队列,负责更行UI的操作。是一个串行的队列。1.2 系统默认的并行队列&#xff1a;global queue&#xff0c;按优先级分类。1.3 自定义的队列&#xff1a;可以创建串行队列或者是并行的队列2.任务2.1 …

java什么叫一致性,java-顺序一致性易失性说明

我正在从Java Jpoint会议观看视频.我对以下来自Alexey Shipilev报告的幻灯片有疑问&#xff1a;打扰一下,请不要打扰我.实际上,作者说不可能将变量集设置为r1 1 (Y)r2 0 (x)r3 1 (x)r4 0 (Y)根据视频,他暗示很明显.有人可以澄清为什么JMM无法设置此值吗&#xff1f;附言如果…

【c++】string类的使用

目录 一、标准库中的string类 1、简单介绍string类 2、string类的常用接口注意事项 2.1、string类对象的常用构造 2.2、string类对象的容量操作 2.3、string类对象的访问及遍历操作 2.4、string类对象的修改操作 二、string类的模拟实现 一、标准库中的string类 1、简…

Java - 对象(object) 具体解释

对象(object) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/24059545 对象(object)的实例能够是 物理对象(如 人, 车等实物) 或 逻辑对象(如 运动, 健康等); 对象是将状态(数据) 和行为(功能) 组合在一起的软件模块. 类是描写叙述一组相似对象共同…

c/c++ 重载运算符 函数调用运算符

重载运算符 函数调用运算符 把一个类的对象a&#xff0c;当成函数来使用&#xff0c;比如a()&#xff0c;所以需要重载operator()方法。重载了函数调用运算符的类的对象&#xff0c;就是函数对象了。 还有什么是函数对象呢&#xff1f;&#xff1f;&#xff1f; lambda是函数对…

matlab 万能,matlab 万能实用的线性曲线拟合方法

在科学计算和工程应用中&#xff0c;经常会遇到需要拟合一系列的离散数据&#xff0c;最近找了很多相关的文章方法&#xff0c;在这里进行总结一下其中最完整、几乎能解决所有离散参数线性拟合的方法第一步&#xff1a;得到散点数据根据你的实际问题得到一系列的散点例如&#…

mysql函数之SUBSTRING_INDEX(str,/,-1)

SUBSTRING_INDEX的用法&#xff1a; •SUBSTRING_INDEX(str,delim,count) 在定界符 delim 以及count 出现前&#xff0c;从字符串str返回自字符串。若count为正值,则返回最终定界符(从左边开始) 若为-1则是从后往前截取 SELECT substring_index(Hn_P00001, P, -1) -- 结果是…

第十二章 Shell脚本编写及常见面试题(三)

本章目录&#xff1a;12.21 FTP下载文件#!/bin/bash if [ $# -ne 1 ]; thenecho "Usage: $0 filename" fi dir$(dirname $1) file$(basename $1) ftp -n -v << EOF # -n 自动登录 open 192.168.1.10 user admin adminpass binary # 设置ftp传输模式为二进制…

省选前的考试记录

日拱一卒功不唐捐 什么沙雕玩意儿 2018.12.24 T1 如果对 \(A\) 数组求出来高度递减的单调栈的话&#xff0c;会发现只有单调栈里的元素是有用的。因为如果有 \(A[i]<A[j] \And i<j\)&#xff0c;那电梯就可以在带 \(j\) 上楼的时候顺便把 \(i\) 带上并不会影响结果。所以…

[Jinkey 原创]震惊!iOS 系统居然自带悬浮窗口调试工具

原文链接 : 震惊&#xff01;iOS 系统居然自带悬浮窗口调试工具 —— Jinkey 原创原文作者 : Jinkey1 背景 英文原文&#xff1a;http://ryanipete.com/blog/ios/swift/objective-c/uidebugginginformationoverlay/ 我写得这个并不是翻译而是用自己的理解重新表述这个功能&…

边分治讲解

前言&#xff1a; 边分治和点分治一样属于树分治的一部分&#xff0c;相比于点分治&#xff0c;边分治对于与度数相关的问题有着很大的优势&#xff0c;同时边分治也是解决树上最优化问题的一种重要的算法。 分治过程&#xff1a; 边分治的分治过程与点分治类似&#xff0c;同样…

Pycharm社区版配置Django

Pycharm开发版(收费)自带Django模板&#xff0c;社区版(免费)需要通过命令行创建Django项目。 通过pip安装Django&#xff1a;pip install django2.0.2(版本号)&#xff0c;可通过以下命令检查是否安装成功 在命令行下创建Django项目(项目存放在D:\PyCharm) 1.创建项目 进入D:\…

用Mesos分布式架构进行工作

引言&#xff1a;2010年&#xff0c;一个旨在解决扩容问题的项目诞生——Apache Mesos&#xff0c;它在某种程度上对CPU、内存、磁盘资源进行抽象&#xff0c;从而允许整个数据中心如同单台大服务器般运转。无需虚拟机和操作系统&#xff0c;Mesos创造了一个单独底层的集群为应…