1. 程式人生 > 其它 >Docker部署MongoDB分片+副本集叢集(實戰)

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.32192.168.1.33192.168.1.35
服務埠mongos:27017mongos:27017mongos:27017
服務埠config server:9001config server:9001config server:9001
服務埠shard1 主節點:9005shard1 副節點:9005shard1 仲裁節點:9005
服務埠shard2 仲裁節點:9006shard2 主節點:9006shard2 副節點:9006
服務埠shard3 副節點:9007shard3 仲裁節點:9007shard3 主節點: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