1. 程式人生 > >Mongodb集群架構之副本集

Mongodb集群架構之副本集

ESS 功能 變化 isod 官方 行數據 相對 aaaaaa java客戶端

本文介紹了熱門的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)整個集群中只有一個主節點。因此寫操作集中於某一個節點上,無法進行對寫操作的負載均衡。

Mongodb集群架構之副本集