您好,登錄后才能下訂單哦!
怎么深入mongodb集群副本集內部機制,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
副本集故障轉移,主節點是如何選舉的?能否手動干涉下架某一臺主節點。
官方說副本集數量最好是奇數,為什么?
mongodb副本集是如何同步的?如果同步不及時會出現什么情況?會不會出現不一致性?
mongodb的故障轉移會不會無故自動發生?什么條件會觸發?頻繁觸發可能會帶來系統負載加重?
Bully算法 mongodb副本集故障轉移功能得益于它的選舉機制。選舉機制采用了Bully算法,可以很方便從分布式節點中選出主節點。一個分布式集群架構中一般都有一個所謂的主節點,可以有很多用途,比如緩存機器節點元數據,作為集群的訪問入口等等。主節點有就有吧,我們干嘛要什么Bully算法?要明白這個我們先看看這兩種架構:
指定主節點的架構,這種架構一般都會申明一個節點為主節點,其他節點都是從節點,如我們常用的mysql就是這樣。但是這樣架構我們在第一節說了整個集群如果主節點掛掉了就得手工操作,上架一個新的主節點或者從從節點恢復數據,不太靈活。
不指定主節點,集群中的任意節點都可以成為主節點。mongodb也就是采用這種架構,一但主節點掛了其他從節點自動接替變成主節點。如下圖:
好了,問題就在這個地方,既然所有節點都是一樣,一但主節點掛了,怎么選擇出來下一個節點是誰來做為主節點呢?這就是Bully算法解決的問題。
那什么是Bully算法,Bully算法是一種協調者(主節點)競選算法,主要思想是集群的每個成員都可以聲明它是主節點并通知其他節點。別的節點可以選擇接受這個聲稱或是拒絕并進入主節點競爭。被其他所有節點接受的節點才能成為主節點。節點按照一些屬性來判斷誰應該勝出。這個屬性可以是一個靜態ID,也可以是更新的度量像最近一次事務ID(最新的節點會勝出)。
選舉 那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.
大致翻譯過來為使用一致協議選擇主節點。基本步驟為:
得到每個服務器節點的最后操作時間戳。每個mongodb都有oplog機制會記錄本機的操作,方便和主服務器進行對比數據是否同步還可以用于錯誤恢復。
如果集群中大部分服務器down機了,保留活著的節點都為 secondary狀態并停止,不選舉了。
如果集群中選舉出來的主節點或者所有從節點最后一次同步時間看起來很舊了,停止選舉等待人來操作。
如果上面都沒有問題就選擇最后操作時間戳最新(保證數據是最新的)的服務器節點作為主節點。
這里提到了一個一致協議(其實就是bully算法),這個和數據庫的一致性協議還是有些區別,一致協議主要強調的是通過一些機制保證大家達成共識;而一致性協議強調的是操作的順序一致性,比如同時讀寫一個數據會不會出現臟數據。一致協議在分布式里有一個經典的算法叫“Paxos算法”,后續再介紹。
上面有個問題,就是所有從節點的最后操作時間都是一樣怎么辦?就是誰先成為主節點的時間最快就選誰。
選舉觸發條件 選舉不是什么時刻都會被觸發的,有以下情況可以觸發。
初始化一個副本集時。
副本集和主節點斷開連接,可能是網絡問題。
主節點掛掉。
選舉還有個前提條件,參與選舉的節點數量必須大于副本集總節點數量的一半,如果已經小于一半了所有節點保持只讀狀態。
日志將會出現:
can't see a majority of the set, relinquishing primary
主節點掛掉能否人為干預?答案是肯定的。
可以通過replSetStepDown命令下架主節點。這個命令可以登錄主節點使用
db.adminCommand({replSetStepDown : 1})
如果殺不掉可以使用強制開關
db.adminCommand({replSetStepDown : 1, force : true})
或者使用 rs.stepDown(120)也可以達到同樣的效果,中間的數字指不能在停止服務這段時間成為主節點,單位為秒。
設置一個從節點有比主節點有更高的優先級。
先查看當前集群中優先級,通過rs.conf()命令,默認優先級為1是不顯示的,這里標示出來。
rs.conf();
{
"_id" : "rs0",
"version" : 9,
"members" : [
{
"_id" : 0,
"host" : "192.168.1.136:27017" },
{
"_id" : 1,
"host" : "192.168.1.137:27017" },
{
"_id" : 2,
"host" : "192.168.1.138:27017" }
]
}
我們來設置,讓id為1的主機可以優先成為主節點。
cfg = rs.conf()
cfg.members[0].priority = 1
cfg.members[1].priority = 2
cfg.members[2].priority = 1
rs.reconfig(cfg)
然后再執行rs.conf()命令查看優先級已經設置成功,主節點選舉也會觸發。
{
"_id" : "rs0",
"version" : 9,
"members" : [
{
"_id" : 0,
"host" : "192.168.1.136:27017" },
{
"_id" : 1,
"host" : "192.168.1.137:27017",
"priority" : 2
},
{
"_id" : 2,
"host" : "192.168.1.138:27017" }
]
}
如果不想讓一個從節點成為主節點可以怎么操作?
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復制指初始化同步過后,節點之間的實時同步一般是增量同步。初始化同步不只是在第一次才會被處罰,有以下兩種情況會觸發:
secondary第一次加入,這個是肯定的。
secondary落后的數據量超過了oplog的大小,這樣也會被全量復制。
那什么是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,節點2、節點3在IDC2,初始化節點2、節點3會從節點1同步數據。后面節點2、節點3會使用就近原則從當前IDC的副本集中進行復制,只要有一個節點從IDC1的節點1復制數據。
設置同步還要注意以下幾點:
secondary不會從delayed和hidden成員上復制數據。
只要是需要同步,兩個成員的buildindexes必須要相同無論是否是true和false。buildindexes主要用來設置是否這個節點的數據用于查詢,默認為true。
如果同步操作30秒都沒有反應,則會重新選擇一個節點進行同步。
到此,本章前面提到的問題全部解決了,不得不說mongodb的設計還真是強大!
后續繼續解決上一節這幾個問題:
主節點掛了能否自動切換連接?目前需要手工切換。
主節點的讀寫壓力過大如何解決?
還有這兩個問題后續解決:
從節點每個上面的數據都是對數據庫全量拷貝,從節點壓力會不會過大?
數據壓力大到機器支撐不了的時候能否做到自動擴展?
關于怎么深入mongodb集群副本集內部機制問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。