mongoDB研究筆記:複製集概述

郭遠威發表於2013-08-24

自我學習,僅供參考:

資料庫總是會遇到各種失敗的場景,如網路連線斷開、斷電等,儘管journaling日誌功能也提供了資料恢復的功能,但journaling通常是針對單個節點來說的,只能保證單節點資料的一致性,而複製集通常是由多個節點組成,每個節點除了journaling日誌恢復功能外,整個複製集還具有故障自動轉移的功能,這樣能保證資料庫的高可用性。在生產環境中一個複製集最少應該包含三個節點,其中有一個必須是主節點,典型的部署結構如下圖:

 

  

其中每個節點都是一個mongod程式對應的例項,節點之間互相週期性的通過心跳檢查對方的狀態,預設情況下primary節點負責資料的讀、寫,second節點備份primary節點上的資料(如何備份?下面會分析),但是arbiter節點不會從primary節點同步資料,從它的名字arbiter可以看出,它起到的作用只是當primary節點故障時,能夠參與到複製集剩下的節點中,選擇出一個新的primary節點,它自己永遠不會變為primary節點,也不會參與資料的讀寫。也就是說,資料庫的資料會存在primary和second節點中,second節點相當於一個備份,當然second節點可以有多個,當primary節點故障時,second節點有可能變為primary節點。上圖是一個生產環境所需的最少節點數,下面就配置一個這樣的複製集。

(1)建立複製集中每個節點存放資料的目錄

E:\mongodb-win32-i386-2.4.3\db_rs0\data\rs0_0

E:\mongodb-win32-i386-2.4.3\db_rs0\data\rs0_1

E:\mongodb-win32-i386-2.4.3\db_rs0\data\rs0_2

(2)建立複製集中每個節點的日誌檔案

      E:\mongodb-win32-i386-2.4.3\db_rs0\logs\rs0_0.log

      E:\mongodb-win32-i386-2.4.3\db_rs0\logs\rs0_1.log

      E:\mongodb-win32-i386-2.4.3\db_rs0\logs\rs0_2.log

 (3)為複製集中的每個節點建立啟動時所需的配置檔案

      第一個節點配置檔案為:E:\mongodb-win32-i386-2.4.3\configs_rs0\rs0_0.conf 內容如下:

      dbpath = E:\mongodb-win32-i386-2.4.3\db_rs0\data\rs0_0

      logpath = E:\mongodb-win32-i386-2.4.3\db_rs0\logs\rs0_0.log

      journal = true

      port = 40000

      replSet = rs0

其中dbpath指向資料庫資料檔案存放的路徑(在第一步中已建立好),logpath指向資料庫的日誌檔案路徑(第二步中已建立好),journal表示對於此mongod例項是否啟動日誌功能,port為例項監聽的埠號,rs0為例項所在的複製集名稱,更多引數的意思可以參考mongoDB手冊。

  第二個節點配置檔案為:E:\mongodb-win32-i386-2.4.3\configs_rs0\rs0_1.conf 內容如下:

dbpath = E:\mongodb-win32-i386-2.4.3\db_rs0\data\rs0_1

logpath = E:\mongodb-win32-i386-2.4.3\db_rs0\logs\rs0_1.log

journal = true

port = 40001

replSet = rs0

第三個節點配置檔案為:E:\mongodb-win32-i386-2.4.3\configs_rs0\rs0_2.conf 內容如下:

dbpath = E:\mongodb-win32-i386-2.4.3\db_rs0\data\rs0_2

logpath = E:\mongodb-win32-i386-2.4.3\db_rs0\logs\rs0_2.log

journal = true

port = 40002

replSet = rs0

(4)啟動上面三個節點對應的mongoDB例項

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

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

mongod –config  E:\mongodb-win32-i386-2.4.3\configs_rs0\rs0_2.conf

觀察一下每個例項的啟動日誌,日誌中都有如下內容:

[rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)

[rsStart] replSet info you may need to run replSetInitiate -- rs.initiate() in the shell -- if that is not already done

上面日誌說明雖然已經成功啟動了三個例項,但是複製集還沒配置好,複製集的資訊會儲存在每個mongod例項上的local資料庫中即local.system.replset上。按照上圖所描述那樣,你應該通過配置確定哪個節點為primary、哪個為second、哪個為arbiter。下面開始配置複製集。

(5)啟動一個mongo客戶端,連線到上面的一個mongod例項

     >mongo --port 40000

執行以下命令初始化複製集

> rs.initiate()

{

    "info2" : "no configuration explicitly specified -- making one",

     "me" : "Guo:40000",

     "info" : "Config now saved locally.  Should come online in about a min e.",

     "ok" : 1

}

這個時候的複製集還只有剛才這個初始化的成員,通過如下命令檢視到。

> rs.conf()

{

        "_id" : "rs0",

        "version" : 1,

        "members" : [

                {

                        "_id" : 0,

                        "host" : "Guo:40000"

                }

        ]

}

按照mongoDB的預設設定,剛才執行初始化命令的這個mongod例項將成為複製集中的primary節點。

(6)接下來在複製集中新增上圖中的second節點和arbiter節點,繼續在上面那個mongod例項上執行如下命令:

rs0:PRIMARY> rs.add("Guo:40001")

{ "ok" : 1 }

rs0:PRIMARY> rs.addArb("Guo:40002")

{ "ok" : 1 }

注意此時命令的字首變為了:rs0:PRIMARY,說明當前執行命令的機器是複製集中primary機器,上面的命令通過rs.add()新增一個預設的second節點,rs.addArb()新增一個預設的arbiter節點。命令成功執行後,就會生成上圖所示那樣的一個複製集。

(7)觀察整個複製集的狀態資訊,幾個重要引數會在後面說明。

rs0:PRIMARY> rs.status()

{

        "set" : "rs0",//複製集的名稱

        "date" : ISODate("2013-08-18T09:03:49Z"),

        "myState" : 1, //當前節點成員在複製集中的位置,如1表示primary,2表示secondry

        "members" : [//複製集的所有成員資訊

                {

                        "_id" : 0, //成員編號

                        "name" : "Guo:40000",//成員所在的伺服器名稱

                        "health" : 1,//成員在複製集中是否執行,1表示執行,0失敗

                        "state" : 1,//成員在複製集中的狀態,1是primary

                        "stateStr" : "PRIMARY",//成員在複製集中的狀態名稱

                        "uptime" : 2186,//成員的線上時間,單位是秒

                        "optime" : {//這個是用來進行同步用的,後面重點分析

                                "t" : 1376816431,

                                "i" : 1

                        },

                        "optimeDate" : ISODate("2013-08-18T09:00:31Z"),

                        "self" : true //成員為當前命令所在的伺服器

                },

                {

                        "_id" : 1,

                        "name" : "Guo:40001",

                        "health" : 1, ,//成員在複製集中是否執行,1表示執行

                        "state" : 2 ,//成員在複製集中的狀態,2是secondary

                        "stateStr" : "SECONDARY",

                        "uptime" : 306,

                        "optime" : {

                                "t" : 1376816431,

                                "i" : 1

                        },

                        "optimeDate" : ISODate("2013-08-18T09:00:31Z"),

                        "lastHeartbeat" : ISODate("2013-08-18T09:03:47Z"),

                        "lastHeartbeatRecv" : ISODate("2013-08-18T09:03:47Z"),

                        "pingMs" : 0,//此遠端成員到本例項間一個路由包的來回時間

                        "syncingTo" : "Guo:40000"//此成員需要從哪個例項同步資料

                },

                {

                        "_id" : 2,

                        "name" : "Guo:40002",

                        "health" : 1,

                        "state" : 7, //成員在複製集中的狀態位置,7是arbiter

                        "stateStr" : "ARBITER",

                        "uptime" : 198,

                        "lastHeartbeat" : ISODate("2013-08-18T09:03:49Z"),

                        "lastHeartbeatRecv" : ISODate("1970-01-01T00:00:00Z"),

                        "pingMs" : 0,//此遠端成員到本例項間一個路由包的來回時間

                }

        ],

        "ok" : 1

}

    上面複製集狀態資訊的輸出是基於primary例項的,也可以再secondary例項上輸出複製集的狀態資訊,包含的欄位與上面大致相同。上面的輸出有些地方還需進一步解釋,如在arbiter成員節點上,沒有欄位syncingTo,說明他不需要從primary節點上同步資料,因為它只是一個當主節點發生故障時,在複製集中剩下的secondary節點中選擇一個新的priamry節點的仲裁者,因此執行此例項的機器不需要太多的儲存空間。

上面輸出的欄位中還有幾個時間相關的欄位如:"date"表示當前例項所在伺服器的時間,"lastHeartbeat"表示當前例項到此遠端成員最近一次成功傳送與接收心跳包的時間,通過比較這個兩個時間可以判斷當前例項與此成員相差的時間間隔,比如某個成員當機了,本例項發像此當機成員的心跳包就不會被成功接收,隨著時間推移,本例項的data欄位值與此成員上的lastHeartbeat差值就會逐漸增加。

上面還有一個optime欄位,這個欄位的值說明了本例項最近一次更改資料庫的時間"t" : 1376816431以及每秒執行的運算元據庫的次數"i" : 1,此欄位的值實際上是從本例項上的local資料庫中的oplog.rs集合上讀取的,這個集合還詳細記錄了具體是什麼操作,如插入語句、修改語句等。複製集中的每一個例項都會有一個這樣的資料庫和集合,如果複製集執行正常,理論上來說,每一個mongod例項上此集合中的記錄應該相同。實際上mongoDB也是根據此集合來實現複製集中primary節點與secondary節點間的資料同步。

相關文章