MongoDB複製集與Raft協議異同點分析
此文已由作者溫正湖授權網易雲社群釋出。
歡迎訪問網易雲社群,瞭解更多網易技術產品運營經驗。
一、日誌複製流程:
a、raft leader節點在接收client請求後,先將請求寫到日誌中,再將日誌通過AppendEntries RPC傳送到follow上。如果收到了大多數follow的確認訊息,則對應日誌可以在leader節點回放,之後follow上對應的日誌也會被應用;
b、mongodb primary節點在接收到client/driver請求後,將資料變化寫到資料庫上,同時寫一份日誌到oplog.rs集合中,secondary節點通過tail cursor將日誌從primary(或sync source,即複製源)拉取到本地馬上進行回放(不會像mysql relay一樣快取到磁碟上),回放完成前將對應的oplog日誌儲存到本節點的oplog.rs集合。
//顯然有幾點不一樣:
1、raft是主動推日誌,mongodb是secondary拉日誌; 相對來說,拉取的方式可以減輕主節點的負擔。這點mongodb好些。
2、raft先寫日誌,日誌傳送到大多數節點後再應用到狀態機。mongodb是先寫資料,然後寫日誌,再通過日誌拉取的方式應用到從節點。 如果日誌比資料小,那麼raft更具有效能優勢,否則,相差無幾。
二、什麼時候返回客戶端:
a、raft中, 是大多數節點已收到,還是寫入leader日誌時? 通過“● Once new entry committed: Leader executes command in its state machine, returns result to client”這句話可以知道,raft是等大多數節點收到日誌,leader將日誌應用到本節點後才返回客戶端;
b、mongodb中,什麼時候返回客戶端可以由使用者進行動態設定,設定項為writeConcern,通過rs.conf()可以獲取當前預設的writeConcern,預設置為w=1,即寫了primary後即返回。也可以在每次寫操作時設定writeConcern,主要包括寫入到幾個節點,寫入超時是多少,是否需要寫日誌等。
// 所以,在這點上mongodb更加靈活,但早期設定的writeConcern級別太鬆,導致丟資料嚴重。目前設定為寫了primary節點再返回客戶端。
三、從節點什麼時候應用日誌:
a、raft中,AppendEntries RPC攜帶了當前已經committed的log的資訊,這樣從節點就可以根據該資訊來將這之前的log應用到本節點;
b、mongod中,從節點從複製源獲取oplog資訊後,馬上在本節點並行回放;
//這點,mongod會更加簡潔。
四、誰能成為主節點:
a、raft,“Only servers with up-to-date logs can become leader”只有擁有最新資料的節點才能成為主。// 4.21更新,raft也是跟MongoDB複製集一樣,資料比大多數節點性就可以。官方ppt中的這句話,up-to-date翻譯成最新容易引起誤解。
b、資料比大多數節點新就可以成為主節點,新主節點在提供對外服務前,會有catchupTimeoutMills時間的catchup過程,用來短暫複製其他節點更新的資料;
//資料是否比大多數節點新,判斷依據是根據日誌來的
五、如何確保每個節點在一個term中只投票一次:
a、raft “Each server gives only one vote per term (persist on disk)”,也就是說會將相應資訊持久化到磁碟上,具體可參考mongodb。
b、mongodb將投票資訊持久化到local庫下replset.election中,內容如:{ "_id" : ObjectId("58cbe1844857daa6e06ed9da"), "term" : NumberLong(4), "candidateIndex" : NumberLong(0) },記錄了在那個term中給誰(candidateIndex)投票了。通過_id欄位的ObjectId物件能獲取投票時間。
六、新主是否會做catchup:
a、raft,“Leader’s log is “the truth””,主節點的資料是真理,新主產生後,不會從存活的從節點上拷最新的資料;
b、mongodb,預設會有2s的catchup時間,如果發現從節點資料比新主新,那麼在這時間內會catchup
//兩則不同的原因是,mongodb是個AP系統,C無法滿足。存在2種情況,如果設定為w=1,那麼如果主掛了,資料可能丟失。如果w=majority,那麼如果還未滿足majority時,主掛了,也就是說客戶端返回錯誤,但這並不表示資料就寫入失敗了,需要等新主產生後進一步確認,因為即使新主本來沒有這部分資料,也可能在catchup節點從其他節點獲取。所以,這跟mysql等關係型資料庫不一樣。
七、主怎麼知道從已經收到日誌/回放了:
a、raft,通過AppendEntries RPC返回結果;
b、通過replSetUpdatePosition命令;
2017-03-30T10:48:12.839+0800 I COMMAND [conn647] command admin.$cmd command: replSetUpdatePosition { replSetUpdatePosition: 1, optimes: [ { durableOpTime: { ts: Timestamp 1490797135000|2, t: 3 }, appliedOpTime: { ts: Timestamp 1490797135000|2, t: 3 }, memberId: 0, cfgver: 454570 }, { durableOpTime: { ts: Timestamp 1490842087000|1, t: 4 }, appliedOpTime: { ts: Timestamp 1490842087000|1, t: 4 }, memberId: 1, cfgver: 454570 }, { durableOpTime: { ts: Timestamp 1490842087000|1, t: 4 }, appliedOpTime: { ts: Timestamp 1490842087000|1, t: 4 }, memberId: 2, cfgver: 454570 } ], $replData: { term: 4, lastOpCommitted: { ts: Timestamp 1490842087000|1, t: 4 }, lastOpVisible: { ts: Timestamp 0|0, t: -1 }, configVersion: 454570, replicaSetId: ObjectId('58cbe1844857daa6e06ed9d7'), primaryIndex: 0, syncSourceIndex: 0 } } numYields:0 reslen:22 locks:{} protocol:op_command 0ms
replSetUpdatePosition不是週期性的,而是實時的。從節點每完成一次oplog回放,就向其複製源傳送一個replSetUpdatePosition命令。
八、節點間是否有優先順序:
a、raft,大家都是平等的。
b、mongodb,有優先順序概念,priority可以是非負數。浮點型
九、是否支援鏈式複製:
a、raft,不支援;
b、mongodb支援鏈式複製。好處是減小了主上的壓力。尤其是在有很多從節點的場景下。不足之處是,這容易導致某些從節點的複製延遲過大。
網易雲免費體驗館,0成本體驗20+款雲產品!
更多網易技術、產品、運營經驗分享請點選。
相關文章:
【推薦】 6本網際網路技術暢銷書免費送(資料分析、深度學習、程式語言)!
【推薦】 網頁設計簡史看設計&程式碼“隔膜”
【推薦】 Kylin效能調優記——業務技術兩手抓