1. 程式人生 > >MongoDB基礎教程系列--第八篇 MongoDB 副本集實現複製功能

MongoDB基礎教程系列--第八篇 MongoDB 副本集實現複製功能

https://www.cnblogs.com/liruihuan/p/6709741.html

為什麼用複製

為什麼要使用複製呢?如果我們的資料庫只存在於一臺伺服器,若這臺伺服器宕機了,那對於我們資料將會是災難,當然這只是其中一個原因,若資料量非常大,讀寫操作勢必會影響資料庫的效能,這時候複製就顯得相當重要了,因為 MongoDB 可以通過複製,實現讀寫分離。

複製是一種在多個伺服器上同步資料的過程。通過在不同的資料庫伺服器上實現多個數據副本。總之,複製可以使你免受硬體故障與服務中斷的影響,及時恢復資料。由於資料有多個副本,所以可以將其中一個副本用於災難恢復、報告或備份。

複製的作用

  • 保證資料的安全性
  • 保證資料的高可用性(24*7)
  • 使用者災難恢復
  • 不需要停機維護(如備份,重建索引,壓縮等任務)
  • 讀寫的靈活性

那麼,複製是怎麼實現的呢?MongoDB 用副本集實現複製的功能。副本集是一組託管同一資料集的 mongod 物件。在副本集中有三個成員:主節點(Primary)、從節點(Secondary)、仲裁節點(Arbiter)

副本集

先對副本整合員進行說明:

主節點(Primary)

提供所有增、刪、查、改操作

從節點(Secondary)

可以提供查詢服務,這樣就可以減少主節點的壓力,當客戶端進行資料查詢時,請求自動轉到從節點上。

仲裁節點(Arbiter)

仲裁節點是一種特殊的節點,它本身並不儲存資料,主要作用在於,當主節點掛掉以後,通過投票的方式決定哪個從節點成為主節點。如果沒有仲裁節點,如果主節點掛掉,那麼整個副本集中就沒有了主節點。

那麼,副本集是怎麼實現主、從節點的資料同步的呢?原來,主節點上的所有操作都記錄在oplog,從節點定期從主節點獲取這些操作,然後對自己的資料副本執行這些操作,從而保證從節點的資料與主節點一致。

  1. 副本集具有 2 個或多個節點(但一般最少需要 3 個節點)。
  2. 副本集只有一個主節點,其他全是從節點。
  3. 所有資料都是從主節點複製到從節點上的。
  4. 當發生自動故障轉移或維護時,會重新推舉一個新的主節點。
  5. 當失敗節點恢復後,該節點重新又連線到副本集中,重新作為從節點。

下面展示一下典型的 MongoDB 複製圖,客戶端從主節點讀取資料,在客戶端寫入資料到主節點時, 主節點與從節點進行資料互動保障資料的一致性。

副本集特點

  • 具有 N 個節點的叢集
  • 任何節點都可能成為主節點
  • 所有寫入操作必須由主節點來完成
  • 自動故障轉移
  • 自動故障恢復
  • 重新推舉主節點

建立副本集

1、關閉正在執行的 MongoDB 伺服器

2、通過指定 --replSet 選項來啟動mongoDB。--replSet 基本語法格式如下:

1

mongod --port "PORT" --dbpath "YOUR_DB_DATA_PATH" --replSet "REPLICA_SET_INSTANCE_NAME"

範例

因為沒有安裝虛擬機器,就把 MongoDB 資料夾放在C盤、D盤、E盤、F盤,模擬放在多個伺服器上。

1、先啟動C盤上的 MongoDB 伺服器:127.0.0.1:27017,指定埠為27017,並取副本集的名稱為 "myRep"

1

mongod --port 27017 --dbpath c:\data\db --replSet myRep

2、然後啟動D盤上的 MongoDB 伺服器:127.0.0.1:27020,指定埠為27020,並取副本集的名稱為 "myRep"

1

mongod --port 27020 --dbpath d:\data\db --replSet myRep

3、MongoDB 中用 rs.initiate() 命令初始化一個副本集,開啟C盤上的 Mongo shell,輸入以下命令

1

2

3

4

5

6

7

8

9

rs.initiate(

   {

      _id: "myRep",

      members: [

         { _id: 0, host : "127.0.0.1:27017" },

         { _id: 1, host : "127.0.0.1:27020" }

      ]

   }

)

4、除了用 rs.initiate() 命令初始化副本集外,MongoDB 還可以用 rs.add(HOST_NAME:PORT),給副本集新增節點。請記住,使用 rs.add() 之前,一定要用 rs.initiate() 初始化副本集,沒有引數也可以。我們先啟動E盤上 MongoDB 伺服器:127.0.0.1:27022,指定埠為27022,並取副本集的名稱為 "myRep"

1

mongod --port 27022 --dbpath e:\data\db --replSet myRep

5、我們用 rs.add() 命令新增一個節點。把服務連線到 主節點 上,在 Mongo shell 中輸入以下命令

1

rs.add("127.0.0.1:27022")

6、沒有仲裁節點的副本集是不完整的,MongoDB 中使用 rs.addArb(HOST_NAME:PORT) 命令新增仲裁節點。我們先啟動F盤上 MongoDB 伺服器:127.0.0.1:27030,指定埠為27030,並取副本集的名稱為 "myRep"

1

mongod --port 27030 --dbpath f:\data\db --replSet myRep

7、我們用 rs.addArb() 命令新增一個仲裁節點。把服務連線到 主節點 上,在 Mongo shell 中輸入以下命令

1

rs.addArb("127.0.0.1:27030")

8、MongoDB 可以使用 rs.status() 命令檢視副本集的狀態,可以清楚的看出哪個伺服器是主節點,哪個伺服器是從節點,哪個伺服器是仲裁節點。在返回的結果中,members 文件中可以清楚的看到欄位 stateStr 的值,該值標識伺服器屬於哪個型別的節點。通過返回結果可以看到C盤的 MongoDB 伺服器是主節點。因為 status() 返回的結果太長,我就不截圖了。

9、副本集已經建好了,是不是特別想試試它的奧祕啊,我們用 Mongo shell連線到主節點伺服器,新增 user 集合,並新增文件

1

2

3

4

mongodb://127.0.0.1:27017   #連線主節點伺服器

...db

test

myRep:PRIMARY>db.user.insert({"name":"liruihuan","age":18})

10、我們再連線到D盤上的伺服器:127.0.0.1:27020,檢視 test 資料庫中是否有 user 集合,如果有,並檢視 user 中的文件。

1

2

3

4

5

6

7

8

mongodb://127.0.0.1:27020   #連線D盤上的伺服器

...db

test

myRep:PRIMARY>show collections  #檢視資料庫 test 中的集合

user

myRep:PRIMARY>db.user.find()

{"_id" : ObjectId("58f0857b54caa5a0e463db06"), "name" "liruihuan""age" : 18}

myRep:PRIMARY>

哇,我們發現D盤上的伺服器已經存在資料了。