Docker部署MongoDB分片+副本集叢集(實戰)
引言
本次實踐部署mongodb叢集,
主要借鑑於該部落格(https://blog.csdn.net/weixin_42104521/article/details/103731266)。
一、原理簡析
Mongodb一共有三種叢集搭建的方式:
Replica Set(副本集)、
Sharding(切片)
Master-Slaver(主從)
mongoDB目前已不推薦使用主從模式,取而代之的是副本集模式。副本集其實一種互為主從的關係,可理解為主主。
副本集:指將資料複製,多份儲存,不同伺服器儲存同一份資料,在出現故障時自動切換。對應的是資料冗餘、備份、映象、讀寫分離、高可用性等關鍵詞;
本實驗模擬的MongoDB叢集分以下幾個層次或角色
mongos層:請求的入口,是router的角色,相當於監聽,負責將請求分發到對應的儲存資料的shard上,多副本冗餘 config server層:記錄了mongos中使用到的元資料,自動向mongos同步最新的叢集配置,多副本冗餘 shard主節點層:將資料分片,資料庫拆分,並將其分散在不同的機器上,原理是將整個資料集合切塊 塊分散到各個shard中,每個shard只負責總資料的一部分,通過一個均衡器來對各個shard均衡,多副本冗餘 shard副本層:是shard的備份,多副本冗餘 shard仲裁層:用於仲裁,不儲存資料,使用最小的資源,需要基數個仲裁角色,且不能放在同一裝置上
主機角色埠規劃
本次實踐在自建虛擬機器進行,有個別需求的同學,可以購買華為雲ECS進行部署(當前優惠力度大哦) 華為雲-2核4G雲主機低至487元/年
伺服器 | 192.168.1.32 | 192.168.1.33 | 192.168.1.35 |
---|---|---|---|
服務埠 | mongos:27017 | mongos:27017 | mongos:27017 |
服務埠 | config server:9001 | config server:9001 | config server:9001 |
服務埠 | shard1 主節點:9005 | shard1 副節點:9005 | shard1 仲裁節點:9005 |
服務埠 | shard2 仲裁節點:9006 | shard2 主節點:9006 | shard2 副節點:9006 |
服務埠 | shard3 副節點:9007 | shard3 仲裁節點:9007 | shard3 主節點:9007 |
可以看到每臺主機上有1個mongos、1個config server、3個分片,三臺主機的相同分片之間構成了主、副和仲裁三個角色。
總結
應用請求mongos來操作mongodb的增刪改查
配置伺服器儲存資料庫元資訊,並且和mongos做同步
資料最終存入在shard(分片)上
為了防止資料丟失同步在副本集中儲存了一份
仲裁在資料儲存到分片的時候決定儲存到哪個節點
二、部署配置伺服器
建立掛載目錄、配置檔案
mkdir /data/mongod/configdata/configsvr -p //三臺主機都執行
mkdir /data/mongod/conf/{configsvr,keyfile} -p // keyfile在開啟使用者認證時需要
配置檔案
# vim /data/mongod/conf/configsvr/mongod.conf
net:
bindIpAll: true
replication:
replSetName: rs_configsvr # 副本集名稱,相同副本須使用同一個副本集名稱
sharding:
clusterRole: configsvr # 定義為mongo配置伺服器
啟動configsvr
## 三臺主機均執行此操作
docker run -d -p 9001:27019 --name configsvr \
--entrypoint "mongod" \
-v /data/mongod/configdata/configsvr:/data/configdb \
-v /data/mongod/conf/keyfile:/data/keyfile \
-v /data/mongod/conf/configsvr:/data/conf \
mongo:4.0.21 -f /data/conf/mongod.conf
備註:如果docker ps 沒有剛才建立的容器名稱,可以使用docker logs <容器id>檢視docker 日誌
初始化配置服務複製集
# 進入容器中,建立的三個配置服務中隨便一個
docker exec -it configsvr bash
# 登入mongo
mongo --host 192.168.1.32 --port 9001
# 初始化
use admin
rs.initiate({
_id: "rs_configsvr",
configsvr: true,
members: [
{ _id : 0, host : "192.168.1.32:9001" },
{ _id : 1, host : "192.168.1.33:9001" },
{ _id : 2, host : "192.168.1.35:9001" }
]
}
)
rs.status() //檢視狀態
三、建立分片副本集
建立分片副本集配置檔案、掛載檔案
## 建立配置檔案、資料目錄
mkdir /data/mongod/shard1/{log,db} -p
mkdir /data/mongod/shard2/{log,db} -p
mkdir /data/mongod/shard3/{log,db} -p
chmod -R 777 /data/mongod/shard1
chmod -R 777 /data/mongod/shard2
chmod -R 777 /data/mongod/shard3
mkdir -p /data/mongod/conf/{shard1,shard2,shard3}
## 三臺主機均建立三個配置檔案,shard分片名不同即可
#所有用到的資料夾和檔案必須在建立的時候給許可權,包括重新建立,也需要重新給許可權,並且資料夾要提前建立好
# vim /data/mongod/conf/{shard1,shard2,shard3}/mongod.conf //新增如下配置資訊,分片服務名稱不一致即可
storage:
dbPath: /home/mongod/db #分片資料庫路徑
journal:
enabled: true
directoryPerDB: true
systemLog:
destination: file
logAppend: true
path: /home/mongod/log/mongod.log # 分片日誌
net:
bindIpAll: true
setParameter:
enableLocalhostAuthBypass: false
replication:
replSetName: rs_shardsvr1 # 分片服務名稱
sharding:
clusterRole: shardsvr # 配置為分片服務
注意事項:
1、需要提前建立需要的資料夾。並賦予許可權(chmod -R 750 資料夾)。
2、三個分片伺服器建立在三個位置,(docker程式碼 -v 引數即為實際建立需要的資料夾),需要注意對應建立分片配置檔案,檔案內容一致。
3、注意配置檔案中的資料庫檔案報錯路徑以及日誌檔案路徑,按需更改。
4、分片服務埠需要對映 27018
shard1 分片
1、mongod分片部署
## 三臺主機(192.168.1.32、33、35)執行如下啟動命令
docker run --name shardsvr1 -d -p 9005:27018 \
--entrypoint "mongod" \
-v /data/mongod/shard1:/home/mongod \
-v /data/mongod/conf/keyfile/:/data/keyfile/ \
-v /data/mongod/conf/shard1/:/data/conf/ \
mongo:4.0.21 -f /data/conf/mongod.conf
2、初始化分片伺服器
# 登入進容器中,任意一臺
docker exec -it shardsvr1 bash
# 登入分片伺服器
# 192.168.1.32 主分片節點
# 192.168.1.33 副分片節點
# 192.168.1.35 仲裁分片節點,arbiterOnly:true 表示為仲裁節點
mongo --host 192.168.1.32 --port 9005
use admin
rs.initiate(
{
_id : "rs_shardsvr1",
members: [
{ _id : 0, host : "192.168.1.32:9005",priority:5 },
{ _id : 1, host : "192.168.1.33:9005",priority:3 },
{ _id : 2, host : "192.168.1.35:9005",arbiterOnly:true }
]
}
)
#rs.status() 檢視狀態
shard2 分片
1、mongod分片部署
## 三臺主機(192.168.1.32、33、35)執行如下啟動命令
docker run --name shardsvr2 -d -p 9006:27018 \
--entrypoint "mongod" \
-v /data/mongod/shard2:/home/mongod \
-v /data/mongod/conf/keyfile/:/data/keyfile/ \
-v /data/mongod/conf/shard2/:/data/conf/ \
mongo:4.0.21 -f /data/conf/mongod.conf
2、初始化分片伺服器
# 登入進容器中,儘量在主節點執行,否則會報錯
docker exec -it shardsvr2 bash
#登入分片伺服器
# 192.168.1.32 仲裁分片節點
# 192.168.1.33 主分片節點
# 192.168.1.35 副分片節點
mongo --host 192.168.1.33 --port 9006
use admin
rs.initiate(
{
_id : "rs_shardsvr2",
members: [
{ _id : 0, host : "192.168.1.32:9006",arbiterOnly:true },
{ _id : 1, host : "192.168.1.33:9006",priority:5 },
{ _id : 2, host : "192.168.1.35:9006",priority:3 }
]
}
)
#rs.status() 檢視狀態
shard3 分片
1、mongod分片部署
## 三臺主機(192.168.1.32、33、35)執行如下啟動命令
docker run --name shardsvr3 -d -p 9007:27018 \
--entrypoint "mongod" \
-v /data/mongod/shard3:/home/mongod \
-v /data/mongod/conf/keyfile/:/data/keyfile/ \
-v /data/mongod/conf/shard3/:/data/conf/ \
mongo:4.0.21 -f /data/conf/mongod.conf
2、初始化分片伺服器
# 登入進容器中,任意節點
docker exec -it shardsvr3 bash
# 登入分片伺服器
# 192.168.1.32 副分片節點
# 192.168.1.33 仲裁分片節點
# 192.168.1.35 主分片節點
mongo --host 192.168.1.35 --port 9007 // 儘量在主節點執行,否則可能會出現報錯
use admin
rs.initiate(
{
_id : "rs_shardsvr3",
members: [
{ _id : 0, host : "192.168.1.32:9007",priority:3 },
{ _id : 1, host : "192.168.1.33:9007",arbiterOnly:true },
{ _id : 2, host : "192.168.1.35:9007",priority:5 }
]
}
)
#rs.status() 檢視狀態
四,建立mongos,連線mongos到分片叢集
建立mongos配置檔案
mkdir /data/mongod/conf/mongos -p //三臺主機都執行
vim /data/mongod/conf/mongos/mongod.conf
## 配置檔案
net:
bindIpAll: true
sharding:
configDB: rs_configsvr/192.168.1.32:9001,192.168.1.33:9001,192.168.1.35:9001 # 定義為mongos配置伺服器
mongos 部署
1、分片路由部署,三臺均執行相同操作
docker run --name mongos -d \
-p 27017:27017 \
--entrypoint "mongos" \
-v /data/mongod/conf/keyfile/:/data/keyfile/ \
-v /data/mongod/conf/mongos/:/data/conf/ \
mongo:4.0.21 -f /data/conf/mongod.conf
備註:
rs_configsvr/192.168.1.32:9001,192.168.1.33:9001,192.168.1.35:9001: 配置服務名稱/配置服務埠(多個用逗號分隔)
2、初始化mongos
# 進入mongos 容器中
docker exec -it mongos bash
# 連線mongos
mongo --host 127.0.0.1 --port 27017
use admin
# 新增分片伺服器
sh.addShard("rs_shardsvr1/192.168.1.32:9005,192.168.1.33:9005,192.168.1.35:9005")
sh.addShard("rs_shardsvr2/192.168.1.32:9006,192.168.1.33:9006,192.168.1.35:9006")
sh.addShard("rs_shardsvr3/192.168.1.32:9007,192.168.1.33:9007,192.168.1.35:9007")
sh.status() //檢視狀態
開啟分片功能
## db和collection開啟分片功能
雖然資料庫採用分片叢集的方式部署,但如果db和collection不啟用分片的話(預設是不啟用的),資料不會分片儲存,此時如果向叢集中匯入一個db,會將整個db隨機儲存到任意一個分片中,而不是拆分儲存到多個分片。
db啟用分片:
sh.enableSharding("庫名")
sh.enableSharding("<database>")
將上述命令中的“”換成實際的db名。
collection啟用分片:
sh.shardCollection("庫名.集合名",{"key":1})
sh.shardCollection("<database>.<collection>", { <shard key> : "hashed" } )
上述命令中的“< database >.< collection >”為實際的db名和collection名;“{ < shard key > : “hashed” }”為片鍵的集合。
五,測試使用
測試使用
# 任意一節點操作
# 進入mongos 容器中
docker exec -it mongos bash
# 連線mongos
mongo --host 127.0.0.1 --port 27017
use admin
# testdb1開啟分片功能
db.runCommand( { enablesharding : "testdb1"});
db.runCommand( { shardcollection : "testdb1.tab1",key : {id: 1} } )
# 新增資料
use testdb1;
for(var i=1;i<=20000;i++) db.tab1.save({id:i,"test1":"testval1"});
db.tab1.stats();
exit
# 使用testdb1庫
# 迴圈插入資料到testdb1庫的tab1集合中的鍵id中
# 該庫對應的該集合對應的該鍵被設定成了分片
# 檢視分片情況
分別在三個主機上操作配置庫、插入測試資料、檢視測試資料
驗證了副本同步,最後的顯示結果看到 “sharded” : true 表示分片也是成功的
六、開啟登入認證
設定資料庫賬號
在任意mongos節點操作
# 進入mongos 容器中
docker exec -it mongos bash
# 連線mongos
mongo --host 127.0.0.1 --port 27017
mongos> use admin
switched to db admin
mongos> show collections
新增兩個管理員賬號,一個系統管理員:system 一個數據庫管理員:administrator
#先新增系統管理員賬號,用來管理使用者
mongos> db.createUser({user:"system",pwd:"123456",roles:[{role:"root",db:"admin"}]})
# 新增資料庫管理員,用來管理所有資料庫
mongos> db.createUser({user:'administrator', pwd:'123456', roles:[{ role:
mongos> db.auth('administrator','123456') //新增管理員使用者認證,認證之後才能管理所有資料庫
# 退出,用剛才建立的賬號進行登入
mongo 192.168.1.33:27017 -u system -p 123456 --authenticationDatabase admin
mongo 192.168.1.35:27017 -u administrator -p 123456 --authenticationDatabase admin
開啟登入驗證
mkdir /data/mongod/conf/keyfile -p //三臺主機都執行
# 在192.168.1.32節點伺服器上操作
cd /data/mongod/conf/keyfile //切換到指定目錄
openssl rand -base64 756 > key.file //建立一個 keyfile(使用 openssl 生成 756 位 base64 加密的字串)
chmod 600 ./key.file
# 複製檔案到其他主機
scp ./key.file [email protected]:/data/mongod/conf/keyfile
scp ./key.file [email protected]:/data/mongod/conf/keyfile
設定配置檔案
使用訪問控制強制重新啟動複製集的每個成員
# 依次在每臺機器上的mongod(注意是所有的mongod不是mongos)的配置檔案中加入下面一段配置。如我在192.168.1.32上的config server,shard1,shard2,shard3都加入下面的配置檔案
security:
keyFile: /data/keyfile/key.file
authorization: enabled
# 依次在每臺機器上的mongos配置檔案中加入下面一段配置
security:
keyFile: /data/keyfile/key.file
重啟叢集
# 在三臺主機執行如下命令
docker ps |grep mongo |awk -F " " '{print $1}' |xargs -r docker restart