mongoDB研究筆記:複製集故障轉移機制

上面的介紹的數據同步(http://www.cnblogs.com/guoyuanwei/p/3293668.html)至關於傳統數據庫中的備份策略,mongoDB在此基礎還有自動故障轉移的功能。在複製集概述那一節提到過心跳"lastHeartbeat"字段,mongoDB就是靠它來實現自動故障轉移的。 mongod實例每隔2秒就向其它成員發送一個心跳包以及經過rs.staus()中返回的成員的」health」值來判斷成員的狀態。若是出現複製集中primary節點不可用了,那麼複製集中全部secondary的節點就會觸發一次選舉操做,選出一個新的primary節點。如上所配置的複製集中若是primary節點宕機了,那麼就會選舉secondary節點成爲primary節點,arbiter節點只是參與選舉其它成員成爲primary節點,本身永遠不會成爲primary節點。若是secondary節點有多個則會選擇擁有最新時間截的oplog記錄或較高權限的節點成爲primary節點。oplog記錄在前面複製集概述中已經描述過,關於複製集中節點權限配置的問題可在複製集啓動的時候進行設置,也能夠在啓動後從新配置,這裏先略過這一點,集中精力討論故障轉移。html

若是是某個secondary節點失敗了,只要複製集中還有其它secondary節點或arbiter節點存在,就不會發生從新選舉primary節點的過程。mongodb

下面模擬兩種失敗場景:一是secondary節點的失敗,而後過一段時間後重啓(時間不能無限期,不然會致使oplog.rs集合嚴重滯後的問題,須要手動才能同步);二是primary節點失敗,故障轉移發生。數據庫

先分析第一種狀況的測試,當前複製集的配置狀況以下:編程

(1)rs0:PRIMARY> rs.conf()安全

{socket

"_id" : "rs0",編程語言

"version" : 3,測試

"members" : [ui

{htm

"_id" : 0,

"host" : "Guo:40000" //primary節點

},

{

"_id" : 1,

"host" : "Guo:40001" //secondary節點

},

{

"_id" : 2,

"host" : "Guo:40002", //arbiter節點

"arbiterOnly" : true

}

]

}

(2)經過Kill掉secondary節點所在的mongod實例,經過rs.status()命令查看複製集狀態,secondary節點狀態信息以下:

"_id" : 1,

"name" : "Guo:40001",

"health" : 0,

"state" : 8, //表示成員已經down機

"stateStr" : "(not reachable/healthy)",

"uptime" : 0,

"optime" : {

"t" : 1376838296,

"i" : 1

},

"optimeDate" : ISODate("2013-08-18T15:04:56Z")

(3)接着經過primary節點插入一條記錄:

rs0:PRIMARY> db.scores.insert({stuid:2,subject:"english",score:100})

(4)再次查看複製集狀態信息rs.status(),能夠看到primary成員節點上oplpog信息以下:

"optime" : {

"t" : 1376922730,

"i" : 1

},

"optimeDate" : ISODate("2013-08-19T14:32:10Z"),

與上面down機的成員節點比較,optime已經不同,primary節點上要新於down機的節點。

(5)從新啓動Kill掉的節點

>mongod --config E:\mongodb-win32-i386-2.4.3\configs_rs0\rs0_1.conf

查詢複製集狀態信息rs.status(),觀看節點"Guo:40001"的狀態信息以下:

"_id" : 1,

"name" : "GUO:40001",

"health" : 1,

"state" : 2,

"stateStr" : "SECONDARY",

"uptime" : 136,

"optime" : {

"t" : 1376922730, //與上面primary節點一致了

"i" : 1

},

"optimeDate" : ISODate("2013-08-19T14:32:10Z"),

說明secondary節點已經恢復,而且從primary節點同步到了最新的操做數據。進一步經過查詢secondary節點上local數據庫上的oplog.rs集合來進行驗證,發現多了一條下面這樣的記錄:

{ "ts" : { "t" : 1376922730, "i" : 1 }, "h" : NumberLong("-451684574732211704"),

"v" : 2, "op" : "i", "ns" : "students.scores", "o" : { "_id" : ObjectId("52122c

6a99c5a3ae472a6900"), "stuid" : 2, "subject" : "english", "score" : 100 } }

這正是在primary節點上插入的記錄,再次證實數據確實同步過來了。

接下來測試第二種狀況:

(1)將primary節點Kill掉。

查詢複製集的狀態信息rs.status()

"name" : "Guo:40000",

"health" : 0,

"state" : 8,

"stateStr" : "(not reachable/healthy)"

字段"health"的值爲0,說明原來的primary節點已經down機了。

"name" : "Guo:40001",

"health" : 1,

"state" : 1,

"stateStr" : "PRIMARY"

字段"stateStr"值爲"PRIMARY",說明原來secondary節點變成了primary節點。

(2)在新的primary節點上插入一條記錄

rs0:PRIMARY> db.scores.insert({stuid:3,subject:"computer",score:99})

(3)從新恢復"Guo:40000"節點(原來的primary節點)

>mongod --config E:\mongodb-win32-i386-2.4.3\configs_rs0\rs0_0.conf

再次查看複製集狀態rs.status()

"name" : "Guo:40000",

"health" : 1,

"state" : 2,

"stateStr" : "SECONDARY",

"uptime" : 33,

"optime" : {

"t" : 1376924110,

"i" : 1

},

當"Guo:40000"實例被從新激活後,變成了secondary節點,oplog也被同步成最新的了。說明當primary節點故障時,複製集能自動轉移故障,將其中一個secondary節點變爲primary節點,讀寫操做繼續在新的primary節點上進行。原來primary節點恢復後,在複製集中變成了secondary節點。

上面兩中狀況都獲得了驗證,可是有一點要注意,mongDB默認狀況下只能在primary節點上進行讀寫操做。對於客戶端應用程序來講,對複製集的讀寫操做是透明的,默認狀況它老是在primary節點上進行。 mongoDB提供了不少種常見編程語言的驅動程序,驅動程序位於應用程序與mongod實例之間,應用程發起與複製集的鏈接,驅動程序自動選擇primary節點。當primary節點失效,複製集發生故障轉移時,複製集將先關閉與全部客戶端的socket鏈接,驅動程序將返回一個異常,應用程序收到這個異常,這個時候須要應用程序開發人員去處理這些異常,同時驅動程序會嘗試從新與primary節點創建鏈接(這個動做對應用程序來講是透明的)。假如這個時候正在發生一個讀操做,在異常處理中你能夠從新發起讀數據命令,由於讀操做不會改變數據庫的數據;假如這個時候發生的是寫操做,狀況就變得微妙起來,若是是非安全模式下的寫,就會產生不肯定因素,寫是否成功不肯定,若是是安全模式,驅動程序會經過getlasterror命令知道哪些寫操做成功了,哪些失敗,驅動程序會返回失敗的信息給應用程序,針對這個異常信息,應用程序能夠決定怎樣處置這個寫操做,能夠從新執行寫操做,也能夠直接給用戶暴出這個錯誤。

相關文章
相關標籤/搜索