在上一篇文章《搭建高可用mongodb集羣(二)—— 副本集》 介紹了副本集的配置,這篇文章深刻研究一下副本集的內部機制。仍是帶着副本集的問題來看吧!html
Bully算法 mongodb副本集故障轉移功能得益於它的選舉機制。選舉機制採用了Bully算法,能夠很方便從分佈式節點中選出主節點。一個分佈式集羣架構中通常都有一個所謂的主節點,能夠有不少用途,好比緩存機器節點元數據,做爲集羣的訪問入口等等。主節點有就有吧,咱們幹嗎要什麼Bully算法?要明白這個咱們先看看這兩種架構:node
指定主節點的架構,這種架構通常都會申明一個節點爲主節點,其餘節點都是從節點,如咱們經常使用的mysql就是這樣。可是這樣架構咱們在第一節說了整個集羣若是主節點掛掉了就得手工操做,上架一個新的主節點或者從從節點恢復數據,不太靈活。mysql
不指定主節點,集羣中的任意節點均可以成爲主節點。mongodb也就是採用這種架構,一但主節點掛了其餘從節點自動接替變成主節點。以下圖:linux
好了,問題就在這個地方,既然全部節點都是同樣,一但主節點掛了,怎麼選擇出來下一個節點是誰來作爲主節點呢?這就是Bully算法解決的問題。算法
那什麼是Bully算法,Bully算法是一種協調者(主節點)競選算法,主要思想是集羣的每一個成員均可以聲明它是主節點並通知其餘節點。別的節點能夠選擇接受這個聲稱或是拒絕並進入主節點競爭。被其餘全部節點接受的節點才能成爲主節點。節點按照一些屬性來判斷誰應該勝出。這個屬性能夠是一個靜態ID,也能夠是更新的度量像最近一次事務ID(最新的節點會勝出)。詳情請參考NoSQL數據庫分佈式算法的協調者競選還有維基百科的解釋 。sql
選舉 那mongodb是怎進行選舉的呢?官方這麼描述:mongodb
We use a consensus protocol to pick a primary. Exact details will be spared here but that basic process is:數據庫
- get maxLocalOpOrdinal from each server.
- if a majority of servers are not up (from this server’s POV), remain in Secondary mode and stop.
- if the last op time seems very old, stop and await human intervention.
- else, using a consensus protocol, pick the server with the highest maxLocalOpOrdinal as the Primary.
大體翻譯過來爲使用一致協議選擇主節點。基本步驟爲:windows
這裏提到了一個一致協議(其實就是bully算法),這個和數據庫的一致性協議仍是有些區別,一致協議主要強調的是經過一些機制保證你們達成共識;而一致性協議強調的是操做的順序一致性,好比同時讀寫一個數據會不會出現髒數據。一致協議在分佈式裏有一個經典的算法叫「Paxos算法」,後續再介紹。緩存
上面有個問題,就是全部從節點的最後操做時間都是同樣怎麼辦?就是誰先成爲主節點的時間最快就選誰。
選舉觸發條件 選舉不是什麼時刻都會被觸發的,有如下狀況能夠觸發。
選舉還有個前提條件,參與選舉的節點數量必須大於副本集總節點數量的一半,若是已經小於一半了全部節點保持只讀狀態。
日誌將會出現:
主節點掛掉可否人爲干預?答案是確定的。
若是殺不掉可使用強制開關
或者使用 rs.stepDown(120)也能夠達到一樣的效果,中間的數字指不能在中止服務這段時間成爲主節點,單位爲秒。
咱們來設置,讓id爲1的主機能夠優先成爲主節點。
而後再執行rs.conf()命令查看優先級已經設置成功,主節點選舉也會觸發。
若是不想讓一個從節點成爲主節點能夠怎麼操做?
a、使用rs.freeze(120)凍結指定的秒數不能選舉成爲主節點。
b、按照上一篇設置節點爲Non-Voting類型。
當主節點不能和大部分從節點通信。把主機節點網線拔掉,嘿嘿:)
優先級還能夠這麼用,若是咱們不想設置什麼hidden節點,就用secondary類型做爲備份節點也不想讓他成爲主節點怎麼辦?看下圖,共三個節點分佈在兩個數據中心,數據中心2的節點設置優先級爲0不能成爲主節點,可是能夠參與選舉、數據複製。架構仍是很靈活吧!
奇數 官方推薦副本集的成員數量爲奇數,最多12個副本集節點,最多7個節點參與選舉。最多12個副本集節點是由於不必一份數據複製那麼多份,備份太多反而增長了網絡負載和拖慢了集羣性能;而最多7個節點參與選舉是由於內部選舉機制節點數量太多就會致使1分鐘內還選不出主節點,凡事只要適當就好。這個「12」、「7」數字還好,經過他們官方通過性能測試定義出來能夠理解。具體還有哪些限制參考官方文檔《 MongoDB Limits and Thresholds 》。 可是這裏一直沒搞懂整個集羣爲何要奇數,經過測試集羣的數量爲偶數也是能夠運行的,參考這個文章http://www.itpub.net/thread-1740982-1-1.html。後來忽然看了一篇stackoverflow的文章終於頓悟了,mongodb自己設計的就是一個能夠跨IDC的分佈式數據庫,因此咱們應該把它放到大的環境來看。
假設四個節點被分紅兩個IDC,每一個IDC各兩臺機器,以下圖。但這樣就出現了個問題,若是兩個IDC網絡斷掉,這在廣域網上很容易出現的問題,在上面選舉中提到只要主節點和集羣中大部分節點斷開連接就會開始一輪新的選舉操做,不過mongodb副本集兩邊都只有兩個節點,可是選舉要求參與的節點數量必須大於一半,這樣全部集羣節點都沒辦法參與選舉,只會處於只讀狀態。可是若是是奇數節點就不會出現這個問題,假設3個節點,只要有2個節點活着就能夠選舉,5箇中的3個,7箇中的4個。。。
心跳 綜上所述,整個集羣須要保持必定的通訊才能知道哪些節點活着哪些節點掛掉。mongodb節點會向副本集中的其餘節點每兩秒就會發送一次pings包,若是其餘節點在10秒鐘以內沒有返回就標示爲不能訪問。每一個節點內部都會維護一個狀態映射表,代表當前每一個節點是什麼角色、日誌時間戳等關鍵信息。若是是主節點,除了維護映射表外還須要檢查本身可否和集羣中內大部分節點通信,若是不能則把本身降級爲secondary只讀節點。
同步,副本集同步分爲初始化同步和keep複製。初始化同步指全量從主節點同步數據,若是主節點數據量比較大同步時間會比較長。而keep複製指初始化同步事後,節點之間的實時同步通常是增量同步。初始化同步不僅是在第一次纔會被處罰,有如下兩種狀況會觸發:
那什麼是oplog的大小?前面說過oplog保存了數據的操做記錄,secondary複製oplog並把裏面的操做在secondary執行一遍。可是oplog也是mongodb的一個集合,保存在local.oplog.rs裏,可是這個oplog是一個capped collection也就是固定大小的集合,新數據加入超過集合的大小會覆蓋。因此這裏須要注意,跨IDC的複製要設置合適的oplogSize,避免在生產環境常常產生全量複製。oplogSize 能夠經過–oplogSize設置大小,對於linux 和windows 64位,oplog size默認爲剩餘磁盤空間的5%。
同步也並不是只能從主節點同步,假設集羣中3個節點,節點1是主節點在IDC1,節點二、節點3在IDC2,初始化節點二、節點3會從節點1同步數據。後面節點二、節點3會使用就近原則從當前IDC的副本集中進行復制,只要有一個節點從IDC1的節點1複製數據。
設置同步還要注意如下幾點:
到此,本章前面提到的問題所有解決了,不得不說mongodb的設計還真是強大!
後續繼續解決上一節這幾個問題:
還有這兩個問題後續解決:
原創文章,轉載請註明: 轉載自LANCEYAN.COM
本文連接地址: 搭建高可用mongodb集羣(三)—— 深刻副本集內部機制