自我學習,僅供參考:mongodb
數據庫老是會遇到各類失敗的場景,如網絡鏈接斷開、斷電等,儘管journaling日誌功能也提供了數據恢復的功能,但journaling一般是針對單個節點來講的,只能保證單節點數據的一致性,而複製集一般是由多個節點組成,每一個節點除了journaling日誌恢復功能外,整個複製集還具備故障自動轉移的功能,這樣能保證數據庫的高可用性。在生產環境中一個複製集最少應該包含三個節點,其中有一個必須是主節點,典型的部署結構以下圖:shell
其中每一個節點都是一個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.logci
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節點間的數據同步。