使用MongoDB,能夠以單機模式提供服務。但在實際的生產環境中,單機模式將面臨很大的風險,一旦單點數據庫服務出現故障,就會致使服務調用出現錯誤甚至崩潰。所以,在實際生產環境下,須要對MongoDB作相應的主備處理,提升數據庫服務的可用性。javascript
對於提升可用性,一些博文裏提到了使用主從模式(master-slaver)。java
WARNING: Deprecated since version 3.2: MongoDB 3.2 deprecates the use of master-slave replication for components of sharded clusters.mongodb
主從模式是高可用的一種方案。然而上面這段警告裏提到,在高版本的MongoDB(3.2以上)的一些場景中,官方已經不推薦使用主從模式,取而代之的,是使用複製集(Replica Set)的方式作主備處理。數據庫
IMPORTANT: Replica sets replace master-slave replication for most use cases. If possible, use replica sets rather than master-slave replication for all new production deployments. This documentation remains to support legacy deployments and for archival purposes only.bash
所以,本文將介紹如何將單機MongoDB數據庫拓展爲主備模式的複製集,以提升可用性。測試
在複製集中,有且只有一個主節點(primary),能夠包含一個或多個從節點(secondary),主從節點經過心跳檢測來肯定節點是否健康或存活。全部的讀寫操做都是在主節點上進行的,若是要實現讀寫分離,須要進行相應的處理。從節點會根據oplog來複制主節點的數據。url
除了主從節點外,MongoDB的複製集中還存在着一種叫仲裁者(Arbiter)的角色。一個仲裁者節點是比較輕量級的,它不會去複製主庫的數據,所以也就不會成爲主節點;它是在投票選舉階段起做用的——當主節點故障時,仲裁者能夠進行投票。通常來講,不建議一個複製集中包含超過一個仲裁者。spa
當主節點忽然故障後,MongoDB有本身的機制,會自動切換,經過選舉,在從節點中選出一個節點做爲新的主節點。日誌
首先,須要在MongoDB實例的啓動參數中加入replSet,指定複製集的名稱。code
mongod --port 8017 --dbpath /home/work/data/db1 --replSet rstest
複製代碼
對於已有的單機實例,也能夠加入該參數並進行重啓。此外,咱們還須要另外啓動兩個MongoDB實例做爲從節點,注意replSet參數指定的名稱須要相同。
mongod --port 8016 --dbpath /home/work/data/db2 --replSet rstest
mongod --port 8015 --dbpath /home/work/data/db2 --replSet rstest
複製代碼
而後,能夠經過mongo命令鏈接MongoDB服務,進入主節點進行初始化。
mongo 127.0.0.1:8017
複製代碼
rs.initiate({
_id:"rstest", // replSet指定的名稱
members:[{
_id:0,
host:"127.0.0.1:8017" // 主節點ip與端口
}]
})
複製代碼
須要注意的是,若是是將已有單機拓展爲複製集,要在鏈接原單機的實例並在其中運行使其做爲主節點。
最後,再將其餘兩個從節點加入到該複製集中。
rs.add("127.0.0.1:8016")
rs.add("127.0.0.1:8015")
複製代碼
經過rs.status()
查看效果,能夠看到rstest
這個複製集中已經有了三個節點,stateStr
指明瞭節點的類型,health
爲1代表該節點是健康的。
{
"set" : "rstest",
"date" : ISODate("2017-10-31T13:04:16.704Z"),
"myState" : 1,
"members" : [
{
"_id" : 0,
"name" : "127.0.0.1:8017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY", // 節點的類型,主節點
"uptime" : 1508,
"optime" : Timestamp(1509455043, 1),
"optimeDate" : ISODate("2017-10-31T13:04:03Z"),
"electionTime" : Timestamp(1509454568, 2),
"electionDate" : ISODate("2017-10-31T12:56:08Z"),
"configVersion" : 3,
"self" : true
},
{
"_id" : 1,
"name" : "127.0.0.1:8016",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 25,
"optime" : Timestamp(1509455043, 1),
"optimeDate" : ISODate("2017-10-31T13:04:03Z"),
"lastHeartbeat" : ISODate("2017-10-31T13:04:15.657Z"),
"lastHeartbeatRecv" : ISODate("2017-10-31T13:04:15.108Z"),
"pingMs" : 0,
"syncingTo" : "127.0.0.1:8017",
"configVersion" : 3
},
{
"_id" : 2,
"name" : "127.0.0.1:8015",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 13,
"optime" : Timestamp(1509455043, 1),
"optimeDate" : ISODate("2017-10-31T13:04:03Z"),
"lastHeartbeat" : ISODate("2017-10-31T13:04:15.657Z"),
"lastHeartbeatRecv" : ISODate("2017-10-31T13:04:15.661Z"),
"pingMs" : 0,
"configVersion" : 3
}
],
"ok" : 1
}
複製代碼
因爲複製集存在災備時中的切換機制,在主節點故障的狀況下,集羣內其餘從節點會經過投票方式產生新的主節點,所以,不能像單機狀況下那樣,直接鏈接主節點。不然,在MongoDB複製集中主節點故障,自動切換主節點時,數據庫訪問就會出問題。所以鏈接複製集須要特定的鏈接方式。
在MongoDB的鏈接字符串(connection url)中能夠進行指定。
mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
複製代碼
其中能夠指定多個host:port,用英文逗號鏈接,並在最後的option中支持replicaSet參數,用於指定鏈接的複製集。例如:
mongodb://127.0.0.1:8017,127.0.0.1:8016,127.0.0.1:8015/books?replicaSet=rstest
複製代碼
這樣就能夠鏈接上覆制集中的books這個數據庫。
MongoDB複製集的故障機制切換是它自身來保障,在部署好上面一系列的服務後,咱們能夠測試一下當主節點故障時,集羣中的節點狀態與服務可用性。
經過kill主節點MongoDB進程,使用rs.status()
能夠發現,其中一個從節點已經升級爲了主節點(這部分在從節點的日誌中也有體現)。此外,數據查詢依然能夠進行,不會由於主節點的宕機而致使數據服務不可用。