本文介紹了熱門的NoSQL資料庫MongoDB的副本集這種分散式架構的一些概念和操作。主要內容包括: MongoDB副本集相關概念 MongoDB副本集環境搭建 MongoDB副本集的讀寫分離 MongoDB副本集的故障轉移 MongoDB副本集的優點 MongoDB副本集的缺點 1.副本集相關概念 ...
本文介紹了熱門的NoSQL資料庫MongoDB的副本集這種分散式架構的一些概念和操作。主要內容包括:
MongoDB副本集相關概念
MongoDB副本集環境搭建
MongoDB副本集的讀寫分離
MongoDB副本集的故障轉移
MongoDB副本集的優點
MongoDB副本集的缺點
1.副本集相關概念
主節點。
在一個副本集中,只有唯一一個主節點。主節點可以進行數據的寫操作和讀操作。副本集中各個節點的增傷改等配置必須在主節點進行。
從節點。
在一個副本集中,可以有一個或者多個從節點。從節點只允許讀操作,不允許寫操作。在主節點宕機後,會自動在從節點中產生一個新的主節點。
仲裁者。
在一個副本集中,仲裁者節點不保存數據,既不能讀數據,也不能寫數據。作用僅僅限於在從從節點選舉主節點時擔任仲裁作用。
副本集的工作原理。
(i)副本集中的主節點的oplog集合中記錄了主節點中所有引起數據變化的變更操作,包括更新和插入數據。副本集中的從節點從主節點的oplog集合中複製這些操作,從而在從節點上重現這些操作。這就是副本集的數據同步的基本原理。
(ii)在 oplog集合中的每個記錄都是有一個時間戳,從節點據此判斷需要更新哪些數據。主節點的local資料庫中的數據不會被覆制到從節點上。
(iii)對於主節點而言,這些複製操作時非同步進行的,相當於MySQL資料庫中的非同步複製模式,即主節點在寫入數據時無需等待任何從節點複製操作完成,即可進行其它數據的寫入操作。
(iv)從節點第1次同步時會做完整的數據同步,後續通常只做一部分最新數據的同步工作。當時當從節點複製延遲太大時會重新進行完整的數據同步。因為oplog集合是一個固定集合,即裡面的文檔數量的大小是有固定的限制的,不能超過某個大小。因此,當主節點上oplog集合寫滿了後,會清空這個oplog集合。如果在寫滿oplog之前,從節點沒有跟上這個速度,則無法再利用oplog進行增量複製工作,這就是需要完整的數據同步的原因。
(v)數據回滾。
在主節點宕機後自動產生了新的主節點,這時整個副本集認為這個新的主節點的數據是最新的有效數據。如果其他從節點中的數據複製進度超過了這個心的主節點的進度,那麼這些從節點將會自動回滾這些超過新主節點的數據。這個操作就是Mongodb中的數據回滾。
2.副本集環境搭建
現在通過在一臺機器(Centos7)上部署三個mongodb節點,從而搭建一個最簡單的mongodb副本集環境。
埠27017 主節點
埠27018 從節點
埠27019 仲裁節點
假定mongodb相關軟體包已經安裝完畢。
(1)首先建立如下圖的目錄結構,其中data和log都是空目錄。
圖1
建立如下所示的腳本文件,用於快速啟動這3個節點。
圖2
啟動3個節點。
圖3
配置副本集。
連接到主節點27017上,然後初始化副本集並且將另外的一個從節點27018和一個仲裁者節點27019加入到副本集中。
圖4
查看副本集狀態。
replset1:PRIMARY> rs.status();
{
"set" : "replset1",
"date" : ISODate("2018-10-01T04:14:17.567Z"),
"myState" : 1,
"term" : NumberLong(1),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1538367253, 1),
"t" : NumberLong(1)
},
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1538367253, 1),
"t" : NumberLong(1)
},
"appliedOpTime" : {
"ts" : Timestamp(1538367253, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1538367253, 1),
"t" : NumberLong(1)
}
},
"lastStableCheckpointTimestamp" : Timestamp(1538367228, 4),
"members" : [
{
"_id" : 0,
"name" : "11.1.1.11:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 260,
"optime" : {
"ts" : Timestamp(1538367253, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2018-10-01T04:14:13Z"),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "could not find member to sync from",
"electionTime" : Timestamp(1538367226, 2),
"electionDate" : ISODate("2018-10-01T04:13:46Z"),
"configVersion" : 3,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 1,
"name" : "11.1.1.11:27018",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 14,
"optime" : {
"ts" : Timestamp(1538367253, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1538367253, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2018-10-01T04:14:13Z"),
"optimeDurableDate" : ISODate("2018-10-01T04:14:13Z"),
"lastHeartbeat" : ISODate("2018-10-01T04:14:17.405Z"),
"lastHeartbeatRecv" : ISODate("2018-10-01T04:14:16.418Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "11.1.1.11:27017",
"syncSourceHost" : "11.1.1.11:27017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 3
},
{
"_id" : 2,
"name" : "11.1.1.11:27019",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 4,
"lastHeartbeat" : ISODate("2018-10-01T04:14:17.405Z"),
"lastHeartbeatRecv" : ISODate("2018-10-01T04:14:17.424Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"configVersion" : 3
}
],
"ok" : 1,
"operationTime" : Timestamp(1538367253, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1538367253, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
副本集中三個節點的狀態應該是:
埠
節點
狀態
27017
主節點
1,PRIMARY
27018
從節點
2,SECONDARY
27019
仲裁節點
7,ARBITER
3.副本集的讀寫分離
在Mongodb副本集中,主節點負責數據的全部寫入操作,也可以讀取數據。從節點只能讀取數據,而仲裁節點不能讀和寫數據。
因此,在主節點27017上可以進行數據的讀取和寫入操作。
圖5
但是這個時候從節點上並沒有真正的成為這個副本集的正式成員。在從節點執行任何有關數據的操作將會產生一個錯誤:
圖6
只需要在從節點上執行一下這個而操作即可解決問題:
圖7
圖8
在仲裁者節點上同樣需要執行類似的操作,但是仲裁者節點是不保存副本集中的數據的。
圖9
在從節點或者仲裁者節點上寫入數據將會失敗。
圖10
4.副本集的故障轉移
現在通過將副本集中的主節點27017節點停止運行來演示mongodb副本集的故障轉移功能。
(1)停止主節點27017。
圖1
圖11
查看節點狀態。
此時原來的主節點27017處於不可用狀態,而原來的從節點27018節點成為了新的主節點。
圖12
三個節點的新狀態如下所示:
埠
節點
狀態
27017
主節點
8,(not reachable/healthy)
27018
從節點
1,PRIMARY
27019
仲裁節點
7,ARBITER
因為27018節點成為了新的主節點,因此可以進行寫數據的操作了。
圖13
在重新啟動27017節點後發現這個原來的主節點成為了從節點。
圖14
至此,Mongodb的副本集方式的集群部署成功。
4.副本集的優點
(1)部署簡單。
Mongodb的副本集方式的集群,相對於MySQL的MHA或者MM方式的集群而言,部署方面簡單,僅僅使用Mongodb官方軟體的內置功能進行安裝部署,不需要第三方的腳本或者軟體即可完成部署。
(2)故障轉移後,主節點的IP地址發生變化。因此需要客戶端程式來處理這種IP變化。Mongodb的java客戶端 SDK正好提供了這種功能,因此只需要將一個副本集中的主節點和全部從節點都加入到連接地址中即可自動完成這種讀寫分離和故障轉移的功能,即不需要程式員自己寫代碼來檢測和判斷副本集中節點的狀態。
Mongodb的副本集的Java SDK和Redis Cluster的Java SDK對於故障轉移的自動化處理方式,都相當的人性化。
5.副本集的缺點
Mongodb的副本集方式的集群架構有如下的缺點:
(1)整個集群中只有一個主節點。因此寫操作集中於某一個節點上,無法進行對寫操作的負載均衡。