MongoDB-副本集搭建與管理

MongoDB 副本集

1、副本集概念

單節點的 MongoDB 在數據的安全和冗餘方面是比較低的,在生產環境中,咱們爲 MongoDB 配置副本集,這樣能夠提升數據的高可用性和安全性。linux

副本集 :是一組 Mongod 維護相同數據集的實例。副本集能夠包含多個數據承載點和多個仲裁點。在承載數據的節點中,僅有一個節點被視爲主節點,其餘節點稱爲次節點。git

副本集的節點角色:github

  • Primary 主節點,用於承擔
  • Secondary 次節點
  • Arbiter 仲裁節點,也是屬於次節點

主節點接收全部的數據寫入操做,主節點記錄數據的全部更改,即oplogmongodb

副本集架構圖

  • 一個 主節點 兩個次節點(Secondary )

读写主数据库的默认路由图。

  • 一個主節點兩個次節點(一個Secondary 節點,一個Arbiter 節點)

由ä¸"要副本,辅助副本和ä"²è£è€…ç"„成的副本集的图表。

將一個額外的mongod實例添加到副本集做爲 仲裁節點。仲裁節點不維護數據集。仲裁節點的目的是經過響應其餘副本集成員的心跳和選舉請求來維護副本集中的選舉。由於它們不存儲數據集,因此仲裁節點能夠是提供副本集仲裁功能的好方法,其資源成本比具備數據集的全功能副本集成員更低。若是您的副本集具備偶數個成員,請添加仲裁者以免腦裂出現。shell

  • 主節點故障後從新選舉主節點

新ä¸"要选举的图。 在具有两个辅助副本的三个成员副本集中,ä¸"è¦å˜å¾—æ— æ³•è®¿é—®ã€‚ 失åŽ"一个ä¸"要触发选举,其中一个辅助成为新的ä¸"要

在主節點未與配置中的其它成員通訊超過 10s(默認爲10s)的話,則符合條件的次節點將推選本身爲主節點。數據庫

在選舉成功完成以前,副本集沒法處理寫入操做。api

electionTimeoutMillis 默認值爲10000(10s) ,咱們能夠根據本身的項目狀況來升高或者下降該值,咱們在更改該值的時候須要考慮到網絡延遲等因素。安全

默認狀況下,副本集在選取新的主節點的等待時間不超過12秒(主要用於將原有主節點標記爲不可用,並選舉出新的主節點),bash

副本集數據同步

爲了保持次節點與主節點的數據同步,MongoDB 使用兩種方式進行數據的同步:

  • 初始同步, 用於同步主節點的全部數據

    初始同步將全部的數據從副本集的一個成員複製到另一個成員

  • 增量同步,在初始同步後不斷複製新的數據

    在初始同步後不斷複製數據,次節點從主節點中同步複製 Oplog,並在異步過程當中應用這些操做

Oplog 詳解

MongoDB-Oplog詳解

注意

副本集在部署前須要肯定成員數據,副本集最多能有50個節點,可是隻能有7個節點擁有被選舉權,副本集須要具備奇數個投票成員,若是有偶數個的話,能夠添加一個 仲裁者,來保證有奇數個成員,避免腦裂狀況發生,

儘可能使用 主機名 來尋找對應的節點,而不是使用 ip 地址,避免 ip 改變致使配置須要更改。

2、副本集部署

部署準備

部署須要更改 /etc/hosts 文件,將主機名和 ip 地址對應好,不該該使用ip。
使用統一的端口。
建立數據儲存的位置和配置文件的位置。
肯定好副本集的名稱

搭建架構選擇

  • 三節點,一個主節點,一個次節點,一個仲裁節點

    由ä¸"要副本,辅助副本和ä"²è£è€…ç"„成的副本集的图表。

副本集部署

基本環境:
    系統 CentOS  7
    MongoDB 版本 4.0.8

3個節點
fymongodb001 內網IP:172.18.186.161  公網ip: 47.112.129.2  # 主節點
fymongodb002 內網IP: 172.18.186.162  公網ip: 47.112.131.231 # 次節點
fymongodb003 內網IP: 172.18.186.163  公網ip: 47.112.98.64 # 仲裁節點

副本集名稱: fymongodb

三個節點都須要執行

# 下載mongodb 
cat <<EOF >>/etc/hosts
172.18.186.161  fymongodb001
172.18.186.162  fymongodb002
172.18.186.163  fymongodb003
EOF
cd /tmp && wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-4.0.8.tgz
tar -zxf mongodb-linux-x86_64-4.0.8.tgz  
mv  mongodb-linux-x86_64-4.0.8  /opt/mongodb
mkdir  /opt/mongodb/{data,logs}
useradd  mongodb
# 咱們這裏使用的配置文件 是YAML 格式的
wget  https://raw.githubusercontent.com/tobewithyou1996/LinuxGuide/master/MongoDB/mongodb_rep.yaml -P /opt/mongodb/
chown -R mongodb:mongodb /opt/mongodb/
cat <<EOF >>/usr/lib/systemd/system/mongodb.service
[Unit]
Description= mongodb service manager
[Service]
# Other directives omitted
# (file size)
LimitFSIZE=infinity
# (cpu time)
LimitCPU=infinity
# (virtual memory size)
LimitAS=infinity
# (locked-in-memory size)
LimitMEMLOCK=infinity
# (open files)
LimitNOFILE=64000
# (processes/threads)
LimitNPROC=64000
Type=forking
User=mongodb
Group=mongodb
PIDFile=/opt/mongodb/logs/mongod.pid
ExecStart= /opt/mongodb/bin/mongod -f /opt/mongodb/mongodb_rep.yaml
ExecStop= /opt/mongodb/bin/mongod --shutdown   --dbpath /opt/mongodb/data
Restart=always
[Install]
WantedBy=multi-user.target
EOF
# 添加環境變量
echo "export PATH=$PATH:/opt/mongodb/bin" >>/etc/profile
source /etc/profile
# 啓動 
systemctl start  mongodb

主節點操做

# 主節點操做
[root@fymongodb001 tmp]# mongo
MongoDB shell version v4.0.8
connecting to: mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("77f60167-1d37-4796-bf2a-60cfdc4b0526") }
MongoDB server version: 4.0.8
> use admin     # 切換到 admin 數據庫
switched to db admin  
# 初始化副本集,副本集名稱爲 fymongodb ,第一個成員爲本身自己。
> rs.initiate({_id:'fymongodb',members: [{ _id: 0 , host: "fymongodb001:27017"}]}) 
{ "ok" : 1 }  
fymongodb:SECONDARY>   # 接着回車,直到顯示這個節點爲Primary主節點
fymongodb:PRIMARY>  # 接着添加 次節點 fymongodb002
# 添加次節點
fymongodb:PRIMARY> rs.add('fymongodb002:27017')
{
    "ok" : 1,
    "operationTime" : Timestamp(1555663440, 1),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1555663440, 1),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}
# 添加仲裁節點
fymongodb:PRIMARY> rs.addArb("fymongodb003:27017")
{
    "ok" : 1,
    "operationTime" : Timestamp(1555663631, 1),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1555663631, 1),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}
# 查看當前配置
fymongodb:PRIMARY> rs.conf()
{
    "_id" : "fymongodb",
    "version" : 3,
    "protocolVersion" : NumberLong(1),
    "writeConcernMajorityJournalDefault" : true,
    "members" : [
        {
            "_id" : 0,
            "host" : "fymongodb001:27017",
            "arbiterOnly" : false,
            "buildIndexes" : true,
            "hidden" : false,
            "priority" : 1,
            "tags" : {
                
            },
            "slaveDelay" : NumberLong(0),
            "votes" : 1
        },
        {
            "_id" : 1,
            "host" : "fymongodb002:27017",
            "arbiterOnly" : false,
            "buildIndexes" : true,
            "hidden" : false,
            "priority" : 1,
            "tags" : {
                
            },
            "slaveDelay" : NumberLong(0),
            "votes" : 1
        },
        {
            "_id" : 2,
            "host" : "fymongodb003:27017",
            "arbiterOnly" : true,
            "buildIndexes" : true,
            "hidden" : false,
            "priority" : 0,
            "tags" : {
                
            },
            "slaveDelay" : NumberLong(0),
            "votes" : 1
        }
    ],
    "settings" : {
        "chainingAllowed" : true,
        "heartbeatIntervalMillis" : 2000,
        "heartbeatTimeoutSecs" : 10,
        "electionTimeoutMillis" : 10000,
        "catchUpTimeoutMillis" : -1,
        "catchUpTakeoverDelayMillis" : 30000,
        "getLastErrorModes" : {
            
        },
        "getLastErrorDefaults" : {
            "w" : 1,
            "wtimeout" : 0
        },
        "replicaSetId" : ObjectId("5cb98534cd9d16ff3f4fffdc")
    }
}
# rs.status()  查看各個節點的身份

當咱們完成上面的操做的時,咱們主節點更改的數據已是會自動同步到次節點的。

次節點操做

fymongodb002次節點(Secondary)設置容許讀寫操做。

[root@fymongodb002 ~]# mongo
MongoDB shell version v4.0.8
connecting to: mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("f353edd5-d79a-4947-9844-7f9bde98a949") }
MongoDB server version: 4.0.8
fymongodb:SECONDARY> fymongodb:SECONDARY> show dbs;  # 咱們發現沒法讀寫
2019-04-19T17:04:40.852+0800 E QUERY    [js] Error: listDatabases failed:{
    "operationTime" : Timestamp(1555664675, 1),
    "ok" : 0,
    "errmsg" : "not master and slaveOk=false",
    "code" : 13435,
    "codeName" : "NotMasterNoSlaveOk",
    "$clusterTime" : {
        "clusterTime" : Timestamp(1555664675, 1),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
} :
fymongodb:SECONDARY> rs.slaveOk()  # 容許 次節點 進行讀取
fymongodb:SECONDARY> show dbs; # 咱們就能夠查看到次節點的數據了。
admin   0.000GB
config  0.000GB
djx     0.000GB
local   0.000GB
fymongodb:SECONDARY> use djx;
switched to db djx
fymongodb:SECONDARY> show  collections;  # 從主節點同步過來的數據。
djx
lsp

數據同步測試

測試數據的同步,咱們在主節點建立一個集合test 並添加一條數據 'age':38 ,咱們能夠看到次節點也同步了該數據。

故障模擬測試

測試一

模擬主節點 fymongodb001 宕機了,而後查看次節點 fymongodb002 是否會被選舉成爲主節點。

咱們能夠看到 fymongodb002 選舉爲主節點.

測試二

fymongodb002 選舉爲主節點後,fymongodb001 恢復了,fymongodb001 會做爲次節點加入。

測試三

測試在次節點(Secondary)進行數據刪除。是刪除不了的。

fymongodb:SECONDARY> db.test.drop()
2019-04-19T21:48:38.140+0800 E QUERY    [js] Error: drop failed: {
    "operationTime" : Timestamp(1555681711, 1),
    "ok" : 0,
    "errmsg" : "not master",
    "code" : 10107,
    "codeName" : "NotMaster",
    "$clusterTime" : {
        "clusterTime" : Timestamp(1555681711, 1),
        "signature" : {
            "hash" : BinData(0,"I+dFkOHcdqW+La7xvy8JFij+5CY="),
            "keyId" : NumberLong("6681517989155569665")
        }
    }
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
DBCollection.prototype.drop@src/mongo/shell/collection.js:707:1
@(shell):1:1

配置副本集登陸驗證

副本集配置用戶和密碼,登陸主節點,添加admin 用戶。

> use admin
switched to db admin
> db.createUser({ user: "admin", pwd: "9toc7tpji8", roles: [{ role: "root", db: "admin" }] })
Successfully added user: {
    "user" : "admin",
    "roles" : [
        {
            "role" : "root",
            "db" : "admin"
        }
    ]
}

在主節點生成 keyflie 並複製到其它兩個節點

# 生成 keyFile
openssl rand -base64 90 -out /opt/mongodb/keyfile
#並複製到其它兩個節點
scp /opt/mongodb/keyfile  fymongodb002:/opt/mongodb/
scp /opt/mongodb/keyfile  fymongodb003:/opt/mongodb/

更改三個節點的 keyFile 文件權限和全部者

chmod 600 /opt/mongodb/keyfile  # 必定要更改爲 600 權限,否正會報錯
chown mongodb:mongodb /opt/mongodb/keyfile # 更改文件全部者

更改三個節點的 mongodb_rep.yaml 配置文件,將 security 的參數 authorization 設置爲 enabled,並配置

keyFile 的路徑。

security:
   authorization: "enabled" 
   keyFile: '/opt/mongodb/keyfile'
   clusterAuthMode: "keyFile"

而後依次重啓 fymongodb001fymongodb002fymongodb003

# fymongodb001
systemctl  restart  mongodb 
# fymongodb002
systemctl  restart  mongodb 
# fymongodb003
systemctl  restart  mongodb

登錄 fymongodb001,咱們使用 db.auth() 進行登錄驗證。

fymongodb:PRIMARY> show dbs;
fymongodb:PRIMARY> use admin 
switched to db admin
fymongodb:PRIMARY> db.auth('admin','9toc7tpji8')
1
fymongodb:PRIMARY> show  dbs;
admin   0.000GB
config  0.000GB
local   0.000GB

三 、副本集維護

副本集成員如何以單節點啓動

副本集當作單節點啓動須要更改配置文件,主要的配置文件有如下幾點:

  • 註釋副本集名稱設置,replSet=fymongodb
  • 更改端口
  • 若是是分片儲存的,那麼還須要註釋分片配置,添加 skipShardingConfigurationChecks = true。

而後咱們執行維護完後,關閉節點

use admin
db.shutdownServer()

而後還原原來的配置,而後做爲副本集成員加入副本集。

副本集設置節點的優先級

若是咱們想讓某個節點成爲主節點,或者是當主節點 down 了後,你想指定某個節點 優先級更高地成爲 次節點。

cfg = rs.conf()
cfg.members[0].priority = 0.5
cfg.members[1].priority = 0.5
cfg.members[2].priority = 1
rs.reconfig(cfg)

副本集使用備份數據進行啓動

# 使用備份數據進行啓動
mongod --dbpath /data/db 
# 刪除 local 數據庫
use local
db.dropDatabase()
# 指定副本集名稱並以備份數據 啓動
mongod --dbpath /data/db --replSet <replName>
# 啓動副本集
rs.initiate( {
   _id : <replName>,
   members: [ { _id : 0, host : <host:port> } ]
})

副本集數據量比較大時如何添加次節點

當副本集的數據量比較大的時候,咱們添加新的節點的時候,若是使用初始化同步的話,會給主節點形成比較大的壓力。咱們有如下選擇:

  • 暫停當前副本集中的一個次節點,而後將 次節點的數據(data)複製到要新添加的節點的數據目錄。而後再將兩個節點啓動。(建議先測試)

    若是要複製數據文件,請確保您的副本包含local數據庫的內容。

  • 指定同步節點 rs.syncFrom(hostportstr),指定同步節點爲次節點,默認的是同步節點 是主節點。

    可是該設置在從新啓動節點,或者同步指定的新節點的鏈接被關閉了,是會失效的。(建議先測試)

  • 若是咱們決定仍是從主節點進行同步數據。

副本集延遲節點

延遲節點在此未記錄,詳細見官方文檔。

副本集經常使用命令

# 副本集初始化
rs.initiate( {
   _id : "rs0",
   members: [
      { _id: 0, host: "mongodb0.example.net:27017" },
      { _id: 1, host: "mongodb1.example.net:27017" },
      { _id: 2, host: "mongodb2.example.net:27017" }
   ]
})
# 副本集添加成員
rs.add('mongodb3.example.net:27017')
# 副本集添加仲裁節點
rs.addArb('mongodb4.example.net:27017')
# 移除節點
rs.remove('hostportstr')
# 查看當前的配置
rs.conf()
# 查看各個節點狀態和身份
rs.status()
# 設定某個節點多少秒不可成爲主節點
rs.freeze(secs)
# 設置次節點從指定節點同步數據
rs.syncFrom(hostportstr)
# 下降主節點爲次節點,只能在主節點上運行
rs.stepDown([stepdownSecs, catchUpSecs])
# 查看幫助
rs.help()
# 次節點執行,表示容許次節點讀取數據
rs.slaveOk()
# 判斷當前節點是不是主節點
rs.isMaster()
# 查看 Oplog 信息
rs.printReplicationInfo()
#  查看副本集的次節點與主節點延遲
db.printSlaveReplicationInfo()
# 移除原有副本集命令
use local
db.system.replset.remove({})
# 關閉 mongodb進程服務
use admin
db.shutdownServer()

4、注意事項

建議將副本集至少部署在3個可用區。

配置副本集成員,使用的是主機名而不是 ip,由於 ip 可能變更。

副本集包含奇數個投票成員。

錯誤問題

報錯內容:

Failed global initialization: BadValue: replication.replSetName is not allowed when storage.indexBuildRetry is specified

storage 參數 indexBuildRetry 不能與 副本集共存,當開啓 副本集的時候,就須要將indexBuildRetry 參數註釋。官網連接

Changed in version 4.0: The setting storage.indexBuildRetry cannot be used in conjunction withreplication.replSetName.

相關文章
相關標籤/搜索