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.pswp.cn/news/395646.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/395646.shtml
英文地址,請注明出處:http://en.pswp.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…