在一個MongoDB復制集集群中,各個服務器有以下幾種狀態:
- master 主節點,一個復制集有且僅有一台服務器處於Primary狀態,只有主節點才對外提供讀寫服務。如果主節點掛掉,復制集將投票選出一個備節點成為新的主節點。
- slave 備用節點,復制集允許有多台Secondary,每個備用節點的數據與主節點的數據是完全同步的。Recovering 恢復中,當復制集中某台服務器掛掉或者掉線后數據無法同步,重新恢復服務后從其他成員復制數據,這時就處於恢復過程,數據同步后,該節點又回到備用狀態。
- Arbiter 仲裁節點,該類節點可以不用單獨存在,如果配置為仲裁節點,就主要負責在復本集中監控其他節點狀態,投票選出主節點。該節點將不會用於存放數據。如果沒有仲裁節點,那么投票工作將由所有節點共同進行。
准備工作:
- centos7系統及已安裝的docker
- mongodb4.0
- 三台機器 :
主節點:192.168.3.80 ------master(node1)
從節點:192.168.3.81 ------slave(node2)
仲裁節點:192.168.3.103 ------arbiter(node3)
架構圖:

參考鏈接:
https://www.jianshu.com/p/7bfda4943034
步驟:
1.將下面給出的IP地址配置到所有的服務器上面,每一台服務器都要執行如下命令(記得要替換掉IP地址哦):
# export node1=192.168.3.80
# export node2=192.168.3.81
# export node3=192.168.3.103
2.在master服務器上面執行如下的命令,然后把密鑰文件復制到其余兩個服務器的同樣的位置。
# mkdir -p /home/core/mongo-files
# cd /home/core/mongo-files
# openssl rand -base64 741 > mongodb-keyfile
# chmod 600 mongodb-keyfile
# sudo chown 999 mongodb-keyfile
這個密鑰文件的所有者被設置成id為“999”的用戶了,因為在MongoDB的Docker容器中,這個用戶需要有操作密鑰文件的權限
3.傳輸密鑰並添加權限
在master節點上操作,把秘鑰文件mongo-files,復制到slave的/home/core/mongo-files下,命令如下:
scp -r mongodb-keyfile root@192.168.3.81:/home/core/mongo-files
![]()
然后切換到slave節點里,給秘鑰增加權限
chmod 600 mongodb-keyfile
sudo chown 999 mongodb-keyfile
scp -r mongodb-keyfile root@192.168.3.103:/home/core/mongo-files
把秘鑰文件mongo-files,復制到arbiter的/home/core/mongo-files下,命令如下:
在master節點操作:mongodb-keyfile root@192.168.3.103:/home/core/mongo-files
![]()
然后切換到arbiter節點里,給秘鑰增加權限
chmod 600 mongodb-keyfile
sudo chown 999 mongodb-keyfile
4.啟動master(即第一台Docker服務器)的MongoDB容器。它會啟動一個沒有身份驗證機制的容器,所以我們要設置一個用戶。
root@master:/# docker run --name mongo \
-v /home/core/mongo-files/data:/data/db \
-v /home/core/mongo-files:/opt/keyfile \
--hostname="node1.example.com" \
-p 27017:27017 \
-d mongo:4.0 --smallfiles
注:沒mongo:4.0鏡像時,執行上面命令時會自動下載mongo:4.0
現在創建一個admin用戶。我們可以連接到剛剛啟動的mongoDB容器,並進入一個交互式的shell環境
root@master:/# docker exec -it mongo /bin/bash
這時候,我們就進到MongoDB的Docker容器里面了,然后我們要打開一個mongo shell環境:
root@master:/# mongo
上面的命令可以打開mongo shell環境。執行后你會看到這樣的輸出:

切換到admin用戶:
> use admin
switched to db admin
創建一個新的site admin 用戶
> db.createUser( {
user: "siteUserAdmin",
pwd: "password",
roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]});
創建成功的話你會看到如下的成功信息:

創建一個root用戶:
> db.createUser( { user: "siteRootAdmin",
pwd: "password",
roles: [
{
role: "root",
db: "admin"
}
]});
你會看到如下的成功信息:

我們已經創建好了我們以后要使用的幾個用戶,現在我們會退出交互式shell環境(mongo和Docker容器的環境)。我們輸入兩次exit退出去
5.停止並刪除第一個MongoDB實例:
root@master:/# docker stop mongo (停止容器)
root@master:/# docker rm mongo (刪除容器)
6.這次使用密鑰文件啟動第一台MongoDB實例(還是在master上面操作的)
docker run \
--name mongo \
-v /home/core/mongo-files/data:/data/db \
-v /home/core/mongo-files:/opt/keyfile \
--hostname="node1.example.com" \
--add-host node1.example.com:${node1} \
--add-host node2.example.com:${node2} \
--add-host node3.example.com:${node3} \
-p 27017:27017 -d mongo:4.0 \
--smallfiles \
--keyFile /opt/keyfile/mongodb-keyfile \
--replSet "rs0"
注意:
- --keyFile的路徑是/opt/keyfile/mongodb-keyfile,這是正確的。這是密鑰文件在Docker內部的地址,我們用-v選項將密鑰文件映射到容器內部的那個路徑上(即:/opt/keyfile/mongodb-keyfile)。
- --add-host把這些信息添加到Docker容器的/etc/hosts文件中,所以我們可以使用域名而不是IP地址了。在實際的生產環境中這些信息都是DNS,這些參數都可以忽略。
7.連接到副本集上並且安裝配置好它。這還是在node1上面進行的。我們要開啟另外一個新的交互式shell環境進入mongo容器,同時開啟一個mongo shell環境:
root@master:/# docker exec -it mongo /bin/bash
root@master:/# mongo
MongoDB shell version: v4.0.13
>
切換到admin用戶下:
> use admin
switched to db admin
因為我們已經設置了一個密碼,所以這次我們不得不做身份驗證。我們把密碼設置為:password。
> db.auth("siteRootAdmin", "password");
1
現在我們可以開啟副本集:
> rs.initiate()

8.驗證已經初始化的副本集的配置:
>rs0:PRIMARY> rs.conf()

9.在其余的兩個節點啟動MongoDB
在slave上面執行命令:
# docker run \
--name mongo \
-v /home/core/mongo-files/data:/data/db \
-v /home/core/mongo-files:/opt/keyfile \
--hostname="node2.example.com" \
--add-host node1.example.com:${node1} \
--add-host node2.example.com:${node2} \
--add-host node3.example.com:${node3} \
-p 27017:27017 -d mongo:4.0 \
--smallfiles \
--keyFile /opt/keyfile/mongodb-keyfile \--replSet "rs0"
在arbiter上面執行命令:
# docker run \
--name mongo \
-v /home/core/mongo-files/data:/data/db \
-v /home/core/mongo-files:/opt/keyfile \
--hostname="node3.example.com" \
--add-host node1.example.com:${node1} \
--add-host node2.example.com:${node2} \
--add-host node3.example.com:${node3} \
-p 27017:27017 -d mongo:4.0 \
--smallfiles \
--keyFile /opt/keyfile/mongodb-keyfile \
--replSet "rs0"
10.將那兩個節點加到副本集上
回到master節點,如果你在這里按了幾次回車鍵(enter)的話,你會看到下面的提示:“rs0:PRIMARY”。這是因為這個節點是副本集“rs0”的主節點。
首先將節點加入復制集:
rs0:PRIMARY> rs.add("node2.example.com")

rs0:PRIMARY> rs.addArb("node3.example.com")

修改節點的優先級:
db.auth("siteRootAdmin", "password"); --首先授權認證

將主節點的優先級設置為10
PRIMARY>rscfg.members[0].priority = 10
將從節點的優先級設置為2
PRIMARY>rscfg.members[1].priority = 2
PRIMARY> rs.reconfig(rscfg)
查看設置的優先級:
rs0:PRIMARY> rs.conf()

驗證其它節點是否正確的加到這個副本集當中:
rs0:PRIMARY> rs.status()
結果如下說明節點添加成功

從庫開啟讀操作(此時可以測試主庫插入,從庫查看,同步正常):
rs.slaveOk();
show dbs
local 0.000GB
mydb 0.000GB
可能會花幾分鍾的時間來將master上面的數據同步到其余的兩個節點上面。你可以通過查看日志來觀察每一個MongoDB的Docker容器里面發生了什么。在任意一個服務器上面執行下面的命令就可以了:
root@master*:/# docker logs -ft mongo

查看各節點的狀態
rs.status()
查看各節點的配置及優先級
rs.conf()
查看整體狀態:
rs.status()
查看主從節點的切換
停掉主節點
docker stop master_mongo
查看從節點變化
docker stop slave_mongo
可以看到從節點已經變成了primary
當主節點再次啟動
它又再次變為primary
查看主從數據庫同步:
插入數據庫:
rs0:PRIMARY> use admin
rs0:PRIMARY> db.auth('rootAdmin','Admin168+);
rs0:PRIMARY> use Test01
rs0:PRIMARY> db.createUser( {
... ... user: "Test01",
... ... pwd: "password",
... ... roles: [ { role: "dbOwner", db: "Test01" } ]});
rs0:PRIMARY> db.Test01.insert([ { "title" : "fczlm", "year" : 2019, "imdb_rating" : 8.1 },{ "title" : "AAA", "year" : 2020, "imdb_rating" : 7.6 } ]);
查看數據庫
rs0:PRIMARY> show dbs
驗證 主從節點切換
優點:當主庫掛掉,從庫會被選為主庫!當原先掛掉的主庫再次啟動,由於優先級的設置,掛掉的主庫還是會變為主庫

192.168.3.81變為主節點

再次啟動主節點(192.168.3.80)查看其變化

測試 數據庫同步
連接mongo數據庫操作(其它兩台操作同下)
輸入IP地址及端口號
輸入之前創建的root用戶名和密碼
user: "siteUserAdmin"
pwd: "password"

在主節點上創建數據庫
創建思路:


在從節點中認證並查看

在Robo 3T上查驗證

結論
現在你擁有了一個MongoDB集群。你可以自由的在任何時刻添加節點到這個集群上。你甚至可以關閉其中的一個節點,包括主節點,然后觀察一個另外一個節點重新變成了主節點。由於這些數據都被寫在了你的本機文件系統當中了,所以重啟任何一個節點都不是什么大問題。
