MongoDB 複製集的選舉原理

複製的原理

        複製時基於啊哦做日誌 oplog , 相當於 MySQL 中的二進制日誌,只記錄發生改變的記錄。複製是將主節點的oplog 日誌同步並應用到其他從節點的過程。

選舉的原理

      節點類型分爲標準(host)節點 、被動(passive)節點和仲裁(arbiter)節點。

(1)只有標準節點可能被選舉爲活躍(primary)節點,有選舉權。被動節點有完整副本,不可能成爲活躍節點,有選舉權。仲裁節點不復制數據,不可能成爲活躍節點,只有選舉權。

(2)標準節點與被動節點的區別:primary 值高者是標準節點,低者則爲被動節點。

(3)選舉規則是票數高者獲勝,primary 是優先權爲 0~1000 的值,相當於額爲增加 0~1000 的票數。選舉結果:票數高者獲勝;若票數相同,數據新者獲勝。


實驗部署

搭建配置4個 MongoDB 實例 mongodb  、mongpdb2 、mongodb3 、mongodb4 。 IP 地址:192.168.213.184

由於MongoDB 數據庫安裝好後,mongodb 爲默認第一個實例,因此只要再搭建2 ,3,4 實例即可

1. 配置複製集

(1)創建數據文件和日誌文件存儲路徑

[root@localhost ~]# mkdir -p /data/mongodb/mongodb{2,3,4}                #創建數據庫文件2,3,4
[root@localhost ~]# cd /data/mongodb/
[root@localhost mongodb]# ls
mongodb2  mongodb3  mongodb4
[root@localhost mongodb]# mkdir logs
[root@localhost mongodb]# ls
logs  mongodb2  mongodb3  mongodb4
[root@localhost mongodb]# cd logs/
[root@localhost logs]# touch mongodb{2,3,4}.log                            #在 /data/mongodb/logs/ 目錄下的日誌存儲路徑
[root@localhost logs]# chmod  - R 777 /data/mongodb/logs/*.log         #修改目錄權限   
[root@localhost logs]# ls -l
總用量 0
-rwxrwxrwx. 1 root root 0 9月  13 18:43 mongodb2.log
-rwxrwxrwx. 1 root root 0 9月  13 18:43 mongodb3.log
-rwxrwxrwx. 1 root root 0 9月  13 18:43 mongodb4.log

(2)配置實例1 的配置文件,啓用複製集名稱

[root@localhost logs]# vim /etc/mongod.conf
replication:
      replSetName: abc                        #去掉註釋,指定複製集名稱(名稱隨便定義)

創建多實例配置文件

[root@localhost logs]# cp -p /etc/mongod.conf /etc/mongod2.conf        複製生成實例2 的配置文件
[root@localhost logs]# vim /etc/mongod2.conf

systemLog:
   destination: file
   logAppend: true
   path: /data/mongodb/logs/mongodb2.log             #日誌文件位置    

storage:
   dbPath: /data/mongodb/mongodb2                        #數據文件位置
   journal:
     enabled: true

port: 27018             #端口號,默認端口號爲27017,因此實例2 的端口號要與之區別,實例3和4 依次往後排


配置其他實例,與實例2修改一樣,注意端口號

[root@localhost logs]# cp -p /etc/mongod2.conf /etc/mongod3.conf
[root@localhost logs]# cp -p /etc/mongod2.conf /etc/mongod4.conf

(3)啓動服務並查看端口是否開啓

[root@localhost logs]# mongod -f /etc/mongod.conf –shutdown                      #先關閉實例1 的服務,在開啓
killing process with pid: 3997                                   #進程號
[root@localhost logs]# mongod -f /etc/mongod.conf
about to fork child process, waiting until server is ready for connections.
forked process: 4867
child process started successfully, parent exiting


[root@localhost logs]# mongod -f /etc/mongod2.conf                                            #啓動實例2 的服務
about to fork child process, waiting until server is ready for connections.
forked process: 4899
child process started successfully, parent exiting


[root@localhost logs]# mongod -f /etc/mongod3.conf                                             #啓動實例3 的服務
about to fork child process, waiting until server is ready for connections.
forked process: 4927
child process started successfully, parent exiting


[root@localhost logs]# mongod -f /etc/mongod4.conf                                              #啓動實例4 的服務
about to fork child process, waiting until server is ready for connections.
forked process: 4955

查看節點端口是否開啓

[root@localhost logs]# netstat -ntap
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name   
tcp        0      0 0.0.0.0:27019           0.0.0.0:*               LISTEN      4927/mongod        
tcp        0      0 0.0.0.0:27020           0.0.0.0:*               LISTEN      4955/mongod        
tcp        0      0 0.0.0.0:27017           0.0.0.0:*               LISTEN      4867/mongod        
tcp        0      0 0.0.0.0:27018           0.0.0.0:*               LISTEN      4899/mongod
      

(4)查看各實例能否進入 mongodb 數據庫 

[root@localhost logs]# mongo
MongoDB shell version v3.6.7
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.6.7

[root@localhost logs]# mongo --port 27018
MongoDB shell version v3.6.7
connecting to: mongodb://127.0.0.1:27018/
MongoDB server version: 3.6.7
Server has startup warnings:

[root@localhost logs]# mongo --port 27019
MongoDB shell version v3.6.7
connecting to: mongodb://127.0.0.1:27019/
MongoDB server version: 3.6.7
Server has startup warnings:

[root@localhost logs]# mongo --port 27020
MongoDB shell version v3.6.7
connecting to: mongodb://127.0.0.1:27020/
MongoDB server version: 3.6.7

2 . 配置複製集的優先級

(1)登錄默認實例 mongo,重新配置4個節點 MongoDB 複製集,設置兩個標準節點,有個被動節點和一個仲裁節點,命令如下:

根據優先級確定節點: 優先級爲 100的爲標準節點,端口號爲 27017和27018  ,優先級爲0 的爲被動節點,端口號爲27019;仲裁節點爲27020

> cfg={"_id":"abc","members":[{"_id":0,"host":"192.168.213.184:27017","priority":100},{"_id":1,"host":"192.168.213.184:27018","priority":100},{"_id":2,"host":"192.168.213.184:27019","priority":0},{"_id":3,"host":"192.168.213.184:27020","arbiterOnly":true}]}
{
     "_id" : "abc",
     "members" : [
         {
             "_id" : 0,
             "host" : "192.168.213.184:27017",                   #標準節點,優先級爲100
             "priority" : 100
         },
         {
             "_id" : 1,
             "host" : "192.168.213.184:27018",                  #標準節點
             "priority" : 100
         },
         {
             "_id" : 2,
             "host" : "192.168.213.184:27019",                   #被動節點,優先級爲0
             "priority" : 0
         },
         {
             "_id" : 3,
             "host" : "192.168.213.184:27020",                   #仲裁節點
             "arbiterOnly" : true
         }
     ]
}


> rs.initiate(cfg)                    # 初始化複製集
{
     "ok" : 1,
     "operationTime" : Timestamp(1536819122, 1),
     "$clusterTime" : {
         "clusterTime" : Timestamp(1536819122, 1),
         "signature" : {
             "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
             "keyId" : NumberLong(0)
         }
     }
}

(2)使用命令 rs.isMaster()  查看各節點身份

abc:PRIMARY> rs.isMaster()
{
     "hosts" : [                                         #標準節點 
         "192.168.213.184:27017",
         "192.168.213.184:27018"
     ],
     "passives" : [                                    #被動節點
         "192.168.213.184:27019"
     ],
     "arbiters" : [                                     #仲裁節點
         "192.168.213.184:27020"
     ],
     "setName" : "abc",
     "setVersion" : 1,
     "ismaster" : true,
     "secondary" : false,
     "primary" : "192.168.213.184:27017",

(3)此時默認實例已經被選舉爲活躍(primary)節點,可以在數據庫中插入信息了。

abc:PRIMARY> use school                                                 #活躍節點(primory)
switched to db school
abc:PRIMARY> db.info.insert({"id":1,"name":"lili"})                #插入兩條信息
WriteResult({ "nInserted" : 1 })
abc:PRIMARY> db.info.insert({"id":2,"name":"tom"})
WriteResult({ "nInserted" : 1 })

(4)查看日誌記錄所有操作,在默認數據庫 local 中的oplog.rs   查看

abc:PRIMARY> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
school  0.000GB
abc:PRIMARY> use local                  #進入 local 數據庫
switched to db local
abc:PRIMARY> show collections    #顯示
me
oplog.rs
replset.election
replset.minvalid
startup_log
system.replset
system.rollback.id
abc:PRIMARY> db.oplog.rs.find()     #查看日誌記錄所有操作

通過日誌記錄,可以找到剛纔加入的兩條信息

"school.info", "ui" : UUID("2b9c93b6-a58a-4021-a2b4-33f9b19925d8"), "wall" : ISODate("2018-09-13T06:24:44.537Z"), "o" : { "_id" : ObjectId("5b9a02aca106c3eab9c639e5"), "id" : 1, "name" : "lili" } }
{ "ts" : Timestamp(1536819899, 1), "t" : NumberLong(1), "h" : NumberLong("-1447313909384631008"), "v" : 2, "op" : "i", "ns" : "school.info", "ui" : UUID("2b9c93b6-a58a-4021-a2b4-33f9b19925d8"), "wall" : ISODate("2018-09-13T06:24:59.186Z"), "o" : { "_id" : ObjectId("5b9a02bba106c3eab9c639e6"), "id" : 2, "name" : "tom" } }

3.模擬節點故障,如果主節點出現故障,另一個標準節點會選舉成爲新的主節點。

(1)先查看當前狀態,使用命令 rs.status()

abc:PRIMARY> rs.status()

"members" : [
         {
             "_id" : 0,                  
             "name" : "192.168.213.184:27017",               #標準節點,端口27017,作爲主節點
             "health" : 1,
             "state" : 1,
             "stateStr" : "PRIMARY",
             "uptime" : 2481,
             "optime" : {
                 "ts" : Timestamp(1536820334, 1),
                 "t" : NumberLong(1)
             },

{
             "_id" : 1,
             "name" : "192.168.213.184:27018",                 #標準節點 ,端口27018 爲從節點
             "health" : 1,
             "state" : 2,
             "stateStr" : "SECONDARY",
             "uptime" : 1213,
             "optime" : {
                 "ts" : Timestamp(1536820324, 1),
                 "t" : NumberLong(1)
             },

{
             "_id" : 2,
             "name" : "192.168.213.184:27019",               #被動節點, 端口27019位從節點
             "health" : 1,
             "state" : 2,
             "stateStr" : "SECONDARY",
             "uptime" : 1213,
             "optime" : {
                 "ts" : Timestamp(1536820324, 1),
                 "t" : NumberLong(1)
             },

{
             "_id" : 3,
             "name" : "192.168.213.184:27020",                     #仲裁節點
             "health" : 1,
             "state" : 7,
             "stateStr" : "ARBITER",
             "uptime" : 1213,
             "lastHeartbeat" : ISODate("2018-09-13T06:32:14.152Z"),

(2)模擬主節點故障,關閉主節點服務,登錄另一個標準節點端口 27018 ,查看麟能夠一個標準節點是否被選舉爲主節點

abc:PRIMARY> exit
bye
[root@localhost logs]# mongod -f /etc/mongod.conf –shutdown                       #關閉主節點服務
killing process with pid: 4821
[root@localhost logs]# mongo --port 27018                                                           #指定27018 端口進入數據庫

abc:PRIMARY> rs.status()                                                              #查看狀態

"members" : [
         {
             "_id" : 0,
             "name" : "192.168.213.184:27017",
            "health" : 0,                                                 #健康之爲 0 ,說明端口27017 已經宕機了
             "state" : 8,
             "stateStr" : "(not reachable/healthy)",
             "uptime" : 0,
             "optime" : {
                 "ts" : Timestamp(0, 0),
                 "t" : NumberLong(-1)
             },

{
             "_id" : 1,
             "name" : "192.168.213.184:27018",               #此時另一臺標準節點被選舉爲主節點,端口爲 27018
             "health" : 1,
             "state" : 1,
             "stateStr" : "PRIMARY",


             "uptime" : 2812,
             "optime" : {
                 "ts" : Timestamp(1536820668, 1),
                 "t" : NumberLong(2)
             },

{
             "_id" : 2,
             "name" : "192.168.213.184:27019",
             "health" : 1,
             "state" : 2,
             "stateStr" : "SECONDARY",
             "uptime" : 1552,
             "optime" : {
                 "ts" : Timestamp(1536820668, 1),
                 "t" : NumberLong(2)
             },

{
         "_id" : 3,
         "name" : "192.168.213.184:27020",
         "health" : 1,
         "state" : 7,
         "stateStr" : "ARBITER",
         "uptime" : 1552,

其中, health 爲 1 代表健康,0 代表宕機。 state 爲 1 代表主節點,爲 2 代表從節點

(3)將標準節點服務全部關閉,查看被動節點是否會被選舉爲主節點

abc:PRIMARY> exit
bye
[root@localhost logs]# mongod -f /etc/mongod2.conf –shutdown                     #關閉主節點服務
killing process with pid: 4853
[root@localhost logs]# mongo --port 27019                                                                #開啓備用節點服務

abc:SECONDARY> rs.status()

"members" : [
         {
             "_id" : 0,
             "name" : "192.168.213.184:27017",                                   #此時兩個標準節點都處於宕機狀態,健康值爲 0
             "health" : 0,
             "state" : 8,
             "stateStr" : "(not reachable/healthy)",
             "uptime" : 0,
             "optime" : {
                 "ts" : Timestamp(0, 0),
                 "t" : NumberLong(-1)
             },

{
             "_id" : 1,
             "name" : "192.168.213.184:27018",
             "health" : 0,
             "state" : 8,
             "stateStr" : "(not reachable/healthy)",
             "uptime" : 0,
             "optime" : {
                 "ts" : Timestamp(0, 0),
                 "t" : NumberLong(-1)
             },

{
             "_id" : 2,
             "name" : "192.168.213.184:27019",                            #被動節點並沒有被選舉爲主節點,說明被動節點不可能成爲活躍節點
             "health" : 1,
             "state" : 2,
             "stateStr" : "SECONDARY",
             "uptime" : 3102,
             "optime" : {
                 "ts" : Timestamp(1536820928, 1),
                 "t" : NumberLong(2)
             },

{
             "_id" : 3,
             "name" : "192.168.213.184:27020",
             "health" : 1,
             "state" : 7,
             "stateStr" : "ARBITER",
             "uptime" : 1849,

(4)再次啓動標準節點服務,查看主節點能否恢復。

abc:SECONDARY> exit
bye
[root@localhost logs]# mongod -f /etc/mongod.conf                                     #啓動實例1 的服務
about to fork child process, waiting until server is ready for connections.
forked process: 39839
child process started successfully, parent exiting
[root@localhost logs]# mongod -f /etc/mongod2.conf                                   #啓動實例2的服務
about to fork child process, waiting until server is ready for connections.
forked process: 39929
child process started successfully, parent exiting
[root@localhost logs]# mongo

{
             "_id" : 0,
             "name" : "192.168.213.184:27017",                           #端口27017 恢復爲主節點,(與標準節點啓動順序有關,先啓動的爲主節點)
             "health" : 1,
             "state" : 1,
             "stateStr" : "PRIMARY",
             "uptime" : 25,
             "optime" : {
                 "ts" : Timestamp(1536821324, 1),
                 "t" : NumberLong(3)
             },

{
         "_id" : 1,
         "name" : "192.168.213.184:27018",
         "health" : 1,
         "state" : 2,
         "stateStr" : "SECONDARY",
         "uptime" : 14,
         "optime" : {
             "ts" : Timestamp(1536821324, 1),
             "t" : NumberLong(3)
         },

{
         "_id" : 2,
         "name" : "192.168.213.184:27019",
         "health" : 1,
         "state" : 2,
         "stateStr" : "SECONDARY",
         "uptime" : 23,
         "optime" : {

{
         "_id" : 3,
         "name" : "192.168.213.184:27020",
         "health" : 1,
         "state" : 7,
         "stateStr" : "ARBITER",
         "uptime" : 23,

由此可以看出:只有標準節點可能被選舉爲活躍節點(主  primary),被動節點不可能成爲活躍節點,有選舉權。仲裁節點不可能成爲活躍節點。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章