天天看點

MongoDB資料庫三種服務叢集部署安裝文檔MongoDB資料庫服務叢集部署安裝文檔

MongoDB資料庫服務叢集部署安裝文檔

MongoDB資料庫三種服務叢集部署安裝文檔MongoDB資料庫服務叢集部署安裝文檔

MongoDB服務安裝

1.1 擷取MongoDB安裝包

目前登入使用者角色為root 所在目錄為/root 作業系統為 Centos6.1
           

下載下傳位址:https://www.mongodb.com/download-center/community

根據伺服器系統擷取安裝包,目前安裝的機器為centos6.1版本,選擇REHL 6.2版本

wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel62-3.6.12.tgz

1.2 安裝MongoDB

1.2.1 準備工作

建立安裝目錄、資料存放目錄、日志目錄
           
mkdir /opt/mongodb # 程式安裝目錄  
mkdir -p /var/mongodb/data # 資料存放目錄  
mkdir -p /var/mongodb/log # mongodb日志目錄  
           

1.2.2 安裝MongoDB

# 解壓縮檔案  
tar -zxvf mongodb-linux-x86_64-rhel62-3.6.12.tgz  
# 移動檔案到/opt/mongodb  
mv mongodb-linux-x86_64-rhel62-3.6.12/* /opt/mongodb/  
# 删除 空目錄  
rm mongodb-linux-x86_64-rhel62-3.6.12 -r  
           

1.2.3 單執行個體MongoDB配置檔案

mongdodb的服務啟動依賴配置檔案的設定或者純指令行參數來設定,指令行參數的方式測試還好,生成環境上不利于管理,這裡建立配置檔案用來設定mongodb,預設是不存在配置檔案的。

vim /opt/mongodb/mongodb.conf  
# 以下為配置檔案詳細配置
# 資料庫檔案位置  
dbpath=/var/mongodb/data  
# 日志檔案路徑  
logpath=/var/mongodb/log/mongodb.log  
# pid檔案路徑  
pidfilepath=/opt/mongodb/mongod.pid  
# 追加的方式寫日志  
logappend=true  
# 綁定ip 預設綁定127.0.0.1  
bind_ip=127.0.0.1  
# 綁定端口 預設27017  
port=27017  
# 以守護程序的方式運作  
fork=true  
# 不同資料庫存放在不同目錄  
directoryperdb=true # 注意該參數需要伺服器使用XFS filesystem 
# 上述參數如果伺服器使用的非XFS filesystem,啟動會出錯,将該參數改為false
           

wq 儲存配置檔案

詳細的配置參數可參考:

https://www.cnblogs.com/cwp-bg/p/9479945.html

https://www.03sec.com/3176.shtml

YAML格式配置檔案建立

MongoDB在2.6版本開始支援使用yaml格式的配置檔案,官方建議使用yaml格式文檔

上述相同參數的yaml格式配置檔案如下

vim /opt/mongodb/mongodb.yaml  
# ------------以下為yaml格式配置檔案内容----------------  
systemLog:  
  destination: "file"  #日志使用檔案  
  path: "/var/mongodb/log/mongod.log"  #日志檔案路徑  
  logAppend: true  #允許日志追加記錄  
processManagement:  
  fork: true  #背景守護程序啟動  
  pidFilePath: "/opt/mongodb/mongod.pid"  #pid檔案路徑  
net:  
  bindIp: "127.0.0.1"  #綁定ip位址
  port: 27017  #執行個體監聽端口  
storage:  
  dbPath: "/var/mongodb/data"  #資料檔案路徑  
  directoryPerDB: false  #一個庫一個檔案,此參數與伺服器使用的檔案系統有關  
           

注意:以下操作涉及到的配置檔案如無特殊說明,均為yaml格式配置

1.2.4 啟動服務

# -f 指定配置檔案路徑 等同 --config 
# 以下兩個指令二選一 效果完全一緻  
/opt/mongodb/bin/mongod -f /opt/mongodb/mongodb.conf    
/opt/mongodb/bin/mongod -f /opt/mongodb/mongodb.yaml  
           

啟動成功後會提示如下

child process started successfully, parent exiting

使用ps檢視是否成功啟動

ps aux|grep 'mongod'

1.2.5 指定使用者mongodb運作mongodb服務

# 建立使用者組mongodb  
groupadd mongodb  
# 建立使用者 mongodb (不允許登入)  
useradd mongodb -g mongodb -s /bin/false  
# 修改檔案所有者  
chown -R mongodb:mongodb /opt/mongodb # 安裝目錄  
chown -R mongodb:mongodb /var/mongodb # 資料存儲目錄  
# 使用ps檢視是否有mongodb程序  
ps aux|grep 'mongod'  
           

如果有程序,使用kill結束程序

kill -9 [pid]

使用mongodb使用者啟動mongodb服務

sudo -u mongodb -g mongodb /opt/mongodb/bin/mongod -f /opt/mongodb/mongodb.yaml

1.2.6 添加環境變量

vim /etc/profile

檔案最後增加如下配置

export PATH=$PATH:/opt/mongodb/bin

加載配置,使環境變量生效

source /etc/profile

配置成功後,可直接使用指令

mongod -f /opt/mongodb/mongodb.yaml

來開啟mongodb服務

1.2.7 編寫自啟動腳本

源碼安裝的mongodb沒有啟動腳本,需要寫一個啟動腳本

vim /opt/mongodb/mongodb.sh  
#----------------以下為腳本内容-------------------------
#!/bin/bash  
#desc mongodb boot shell   
  
MGDB_PATH="/opt/mongodb"  
MGDB_CONF="${MGDB_PATH}/mongodb.yaml"  
MGDB_USER="mongodb"  
MGDB_GROUP="mongodb"  
cd ${MGDB_PATH}  
  
MGDB_START(){  
  
        if [ ` ps -ef|grep 'mongod -f'|grep -v grep|wc -l` > 0 ];then  
                echo "MongoDB already start"  
                exit 1  
        fi  
    sudo -u ${MGDB_USER} -g ${MGDB_GROUP} ${MGDB_PATH}/bin/mongod -f  ${MGDB_CONF}  
    if [ $? -eq 0 ];then  
        echo -n "MongoDB start "  
        echo -n "["  
        echo -ne "\033[32m"  
        echo -n "Successful"  
        echo -ne "\e[0m"  
        echo  "]"  
    else  
        echo "MongoDB start failed"  
  
    fi  
}  
 
MGDB_STOP(){  
  
        sudo -u ${MGDB_USER} -g ${MGDB_GROUP} ${MGDB_PATH}/bin/mongod -f  ${MGDB_CONF} --shutdown  
        if [ $? -eq 0 ];then  
                echo -n "MongoDB stop "  
                echo -n "["  
                echo -ne "\033[32m"  
                echo -n "Successful"  
                echo -ne "\e[0m"  
                echo  "]"  
        else  
                echo "MongoDB stop failed"  
        fi  
}  
  
MGDB_STATUS(){  
  
    ps -ef|grep 'mongod -f'|grep -v grep   
    if [ $? != 0 ];then  
        echo "MongoDB is STOP"  
    fi  
}  
  
case "$1" in   
    start)  
        MGDB_START  
        ;;  
    stop)  
        MGDB_STOP  
        ;;  
    status)  
        MGDB_STATUS  
        ;;  
    restart)  
        MGDB_STOP  
                MGDB_START  
        ;;  
    *)  
        echo $"Usage: $0 { start | stop | status | restart }"  
        exit 1  
esac  
           

儲存腳本後添加到自啟動程式

# 添加可執行權限  
chmod +x  /opt/mongodb/mongodb.sh  
# 添加自啟動服務  
cp /opt/mongodb/mongodb.sh /etc/init.d/mongodb  
Centos6.x使用service管理服務
# 啟動服務  
service mongodb start  
# 停止服務  
service mongodb stop  
# 檢視服務狀态  
service mongodb status  
 Centos7.x使用service管理服務
# 啟動服務    
systemctl start mongodb  
# 停止服務    
systemctl stop mongodb  
# 檢視服務狀态    
systemctl status mongodb  
           

1.2.8 對外提供服務

# 修改/opt/mongodb/mongodb.yaml  
vim /opt/mongodb/mongodb.yaml  
# 将bindIp修改為0.0.0.0  
bindIp=0.0.0.0  
# 儲存  
# 重新開機 mongodb服務  
service mongodb restart  
           

Centos6.x

檢視防火牆狀态

service iptables status

如果防火牆開啟狀态,則關閉防火牆

service iptables stop

Centos7.x

systemctl stop firewalld.service

1.2.9 使用shell操作mongodb

直接執行如下指令 可連接配接到本地mongodb服務

mongo

使用參數可指定伺服器

mongo --host x.x.x.x --post 27017

叢集部署配置

2.1 準備工作

現有機器M5-M9,ip位址如下

機器名 ip位址 說明
M5 10.1.1.245
M6 10.1.1.246
M7 10.1.1.247
M8 10.1.1.248
M9 10.1.1.249

所有機器按如上步驟,部署成單機版本mongodb

快捷方式

注意本快捷方式僅适用于此次的環境,非通用。可略過此部分内容。

因為MongoDB的安裝方式僅僅是解壓縮,相當于windows上的綠色程式,不存在編譯過程,伺服器系統一緻的情況下,可将安裝好的mongdb打包,發送到需要部署的機器上。

cd /opt && zip mongodb.zip mongodb -r  
# 使用scp遠端複制到需要部署的伺服器  
scp mongodb.zip [email protected]:/opt   
# 依次執行以下指令可完成安裝部署  
unzip /opt/mongodb.zip -d /opt  
mkdir -p /var/mongodb/data  
mkdir -p /var/mongodb/log  
useradd mongodb  
chown -R mongodb:mongodb /var/mongodb  
chown -R mongodb:mongodb /opt/mongodb  
cp /opt/mongodb/mongodb.sh /etc/init.d/mongodb  
echo 'export PATH=$PATH:/opt/mongodb/bin' >> /etc/profile  
source /etc/profile  
service mongodb start  
           

2.2 說明

MongoDB共有三種叢集搭建方式,分别為

Replica Set(副本集)、

Sharding(分片)

Master-Slaver(主從)【目前已不推薦使用!!!】

三種叢集方式的詳細說明在下面的部署方案中,實作的方式都是通過更改配置來實作的,是以不同的部署方式有不同的配置檔案,叢集部署的配置檔案命名規則統一為如下格式

mon_xx_yy_0.yaml

mon : 固定格式 代表mongodb

xx : 代表叢集方式 枚舉[‘ms’,’rs’,’s’] 分别代表三種部署方式首字母小寫

yy : 代表所在叢集方式中的節點類型

ms叢集中 包含[‘master’,’slaver’]兩種

rs叢集中 包含[‘primary’,’ secondaries’,’ arbiter’]三種

s叢集中 包含[‘shard,’config’, ’route’]兩種

0 : 啟動權重, 叢集部署的機器有啟動順序的要求。0為首先需要啟動的機器,其他機器權重一次後延,同權重機器啟動順序無要求。

備注:啟動失敗就随時檢視日志檔案,失敗的原因會在日志中展示。

2.3 Master-Slaver主從複制 叢集搭建

2.3.1 Master-Slaver部署說明

最簡單的叢集搭建,不過準确說也不能算是叢集,隻能說是主備。

并且官方已經不推薦這種方式,是以在這裡隻是簡單配置,搭建方式也相對簡單。

節點說明:

master:主從複制中的主節點,隻允許有一個,對外提供讀寫服務

slaver: 從節點,不提供服務,隻同步主節點的資料,主節點故障,可手動切換。

官方文檔位址:https://docs.mongodb.com/v3.6/core/master-slave/index.html

優點:搭建簡單、可用于備份、故障恢複、讀擴充等。

缺點:不支援故障轉移,對大量資料的支援較差

備注:可在程式層面實作故障轉移,可用于備份,故障恢複,讀擴充等。

2.3.2 伺服器規劃

所有機器都已部署成單執行個體mongodb伺服器,原配置檔案為所在位置為

/opt/mongodb/mongodb.yaml,不同部署方式有不同的配置檔案。

機器名 ip位址 配置檔案 說明
M5 10.1.1.245 mon_ms_slaver_1.yaml 備節點
M6 10.1.1.246 mon_ms_master_0.yaml 主節點
M7 10.1.1.247 mon_ms_slaver_1.yaml 備節點
M8 10.1.1.248 mon_ms_slaver_1.yaml 備節點
M9 10.1.1.249 mon_ms_slaver_1.yaml 備節點

2.3.3配置檔案編寫

在M6伺服器上編輯master配置檔案

vim /opt/mongodb/mon_ms_master_0.yaml  
# ---------------以下為master伺服器配置--------------------  
systemLog:  
  destination: "file"  #日志使用檔案  
  path: "/var/mongodb/log/mongod.log"  #日志檔案路徑  
  logAppend: true  #允許日志追加記錄  
processManagement:  
  fork: true  #背景守護程序啟動  
  pidFilePath: "/opt/mongodb/mongod.pid"  #pid檔案路徑  
net:  
  bindIp: "10.1.1.246"  #伺服器自己的IP位址
  port: 27017  #執行個體監聽端口  
storage:  
  dbPath: "/var/mongodb/data"  #資料檔案路徑  
  directoryPerDB: false  #一個庫一個檔案此參數與系統檔案有關  
           

在M5伺服器上編輯slaver 配置檔案

vim mon_ms_slaver_1.yaml   
# ----------------以下為slaver伺服器詳細配置--------------------------------  
systemLog:  
  destination: "file"  #日志使用檔案  
  path: "/var/mongodb/log/mongod.log"  #日志檔案路徑  
  logAppend: true  #允許日志追加記錄  
processManagement:  
  fork: true  #背景守護程序啟動  
  pidFilePath: "/opt/mongodb/mongod.pid"  #pid檔案路徑  
net:  
  bindIp: "10.1.1.245" # 伺服器的ip  
  port: 27017  #執行個體監聽端口  
storage:  
  dbPath: "/var/mongodb/data"  #資料檔案路徑  
  directoryPerDB: false  #一個庫一個檔案此參數與系統檔案有關  
           

将slaver配置檔案複制到M7、M8、M9機器上,或者在其他機器上手動建立配置檔案,注意更改IP位址。

2.3.4 服務啟動

登入M6機器,啟動master節點

注意:這裡不能使用啟動腳本來啟動檔案,啟動腳本中的配置檔案固定為單執行個體配置,如需使用啟動腳本,需要更改啟動腳本中的MGDB_CONF變量

# 啟動腳本的修改, 可略過  
vim /etc/init.d/mongodb   
# 原  
MGDB_CONF="${MGDB_PATH}/mongodb.yaml"  
# 修改後  
MGDB_CONF="${MGDB_PATH}/mon_ms_master_0.yaml"  
# 其他slaver伺服器類似,修改配置檔案所在即可  
           

注意:有的時候服務無法啟動,隻是提示使用without --fork 啟動,可通過日志檢視原因,或者在確定資料已備份的前提下,将/var/mongodb/data/ 下的内容清空即可指令如下

rm /var/mongodb/data/* -rf

啟動master

# --master參數 代表目前服務使用master模式運作  
sudo -u mongodb -g mongodb /opt/mongodb/bin/mongod -f /opt/mongodb/mon_ms_master_0.yaml --master  
           

依次登入M5、M7、M8、M9機器使用以下指令啟動slaver節點

# --slave指定運作模式  --source 指定master的ip:port  
sudo -u mongodb -g mongodb /opt/mongodb/bin/mongod -f /opt/mongodb/mon_ms_slaver_1.yaml --slave --source 10.1.1.246:27017  
           

服務成功啟動後,檢視master日志,有用戶端連入的字樣received client metadata

2.3.5 資料同步測試

在任意機器上使用mongo連接配接master, 在主從模式中,隻有master節點可讀寫,slaver節點隻能讀。

mongo --host 10.1.1.246  
# ---以下指令執行環境為mongo的shell用戶端  
use school; # 選擇school庫,沒有會建立  
db.createCollection('student'); # 建立名為student的集合  
# 向集合中插入三條資料  
db.student.insert({'name':'Xinu1', score:99});  
db.student.insert({'name':'Xinu2', score:100});  
db.student.insert({'name':'Xinu3', score:80});  
exit  
# 更換任意slaveer節點,檢視資料是否同步  
mongo --host 10.1.1.249  
# ---以下指令執行環境為mongo的shell用戶端  
rs.slaveOk(); # 正常slaver節點不允許讀取操作,使用此方法,擷取目前連接配接臨時讀取授權  
show dbs; # 檢視目前節點中的資料庫  
use school;  
show collections; # 檢視目前節點中的集合  
db.student.find(); # 檢視集合student中的資料  
           

主從模式搭建費成功的話,可以看到如下圖的資料。主從複制搭建成功。

2.3.6 故障處理

master-slaver複制模式所有的服務都有master提供,master故障後,需要手動調整任意一個slaver節點為master節點

以M5節點為例,将M5節點變為master節點

# 查找目前mongod服務程序号  
ps aux|grep 'mongod'|grep -v grep  
# 殺掉該程序  
kill -9 [pid]  
# 删除 M5節點中資料目錄中的 local.*  
rm /var/mongodb/data/local.* -rf  
# 重命名配置檔案  
mv /opt/mongodb/mon_ms_slaver_1.yaml /opt/mongodb/mon_ms_master_0.yaml  
# 以--master方式運作  
sudo -u mongodb -g mongodb /opt/mongodb/bin/mongod -f /opt/mongodb/ mon_ms_master_0.yaml --master  
           

其他從節點停止服務,重新啟動 參數–source修改為10.1.1.245:27017

2.4 Replica Set副本集 叢集搭建

2.4.1 Replica Set部署說明

官方推薦的搭建方式,同時也是最流行的叢集搭建方式。支援故障自動轉移,讀寫分離,有較好的性能和容災能力。

一個副本集即為服務于同一資料集的多個 MongoDB 執行個體,其中一個為主節點,其餘的都為從節點。主節 點上能夠完成讀寫操作,從節點僅能用于讀操作。主節點需要記錄所有改變資料庫狀态的操作,這些記錄 儲存在 oplog 中,這個檔案存儲在 local 資料庫,各個從節點通過此 oplog 來複制資料并應用于本地,保持 本地的資料與主節點的一緻。oplog 具有幂等性,即無論執行幾次其結果一緻,這個比 mysql 的二進制日 志更好用。

叢集中的各節點還會通過傳遞心跳資訊來檢測各自的健康狀況。當主節點故障時,多個從節點會觸發一次 新的選舉操作,并選舉其中的一個成為新的主節點(通常誰的優先級更高,誰就是新的主節點),心跳信 息預設每 2 秒傳遞一次。

節點說明:

primary:主節點,隻有一個,對外提供讀寫服務,記錄在其上所有操作的 oplog。

secondary: 從節點定期輪詢主節點擷取這些操作,然後對自己的資料副本執行這些操作,進而保證從節點的資料與主節點一緻。預設情況下,從節點不支援外部讀取,但可以設定;副本集的機制在于主節點出現故障的時候,餘下的節點會選舉出一個新的主節點,進而保證系統可以正常運作。

arbiter:仲裁節點,副本集部署非必須部署仲裁節點,仲裁節點是為了更好的選舉主節點。不複制資料,僅參與投票。由于它沒有通路的壓力,比較空閑,是以不容易出故障。由于副本集出現故障的時候,存活的節點必須大于副本集節點總數的一半,

否則無法選舉主節點,或者主節點會自動降級為從節點,整個副本集變為隻讀。是以,增加一個不容易出故障的仲裁節點,可以增加有效選票,降低整個副本集不可用的風險。仲裁節點可多于一個。也就是說隻參與投票,不接收複制的資料,也不能成為活躍節點。如果副本集的節點總數為奇數,則無需部署仲裁節點,節點總數為偶數,則配置一個仲裁節點擁有選舉權。為測試使用仲裁節點,本次部署5個節點,1主3從1仲裁。

官方文檔位址:https://docs.mongodb.com/v3.6/tutorial/deploy-replica-set

其它參考文檔:https://www.cnblogs.com/kevingrace/p/5685486.html

優點:自動故障轉移、自動恢複、讀寫分離

缺點:部署略有難度提升

備注:比較流行的部署方式,滿足大部分業務場景需求

2.4.2 伺服器規劃

所有機器都已部署成單執行個體mongodb伺服器,原配置檔案為所在位置為

/opt/mongodb/mongodb.yaml,不同部署方式有不同的配置檔案。

注意:如果機器部署過其它方式的叢集,在部署前,請清空所有執行個體的data目錄

rm /var/mongodb/data/* -rf

機器名 ip位址 配置檔案 說明
M5 10.1.1.245 mon_rs_arbiter_2.yaml 仲裁節點
M6 10.1.1.246 mon_rs_primary_0.yaml 主節點
M7 10.1.1.247 mon_rs_secondary_1.yaml 從節點
M8 10.1.1.248 mon_rs_secondary_1.yaml 從節點
M9 10.1.1.249 mon_rs_secondary_1.yaml 從節點

2.4.3 配置檔案編寫

Replica Set副本建官方推薦資料開啟auth校驗,下面是開啟auth校驗的準備工作

準備工作(以下操作均在M6節點上)

使用單例模式的配置,開啟服務,使用mongo用戶端連接配接,并建立一個使用者

# 單執行個體模式開啟mongodb服務  
sudo -u mongodb -g mongodb /opt/mongodb/bin/mongod -f /opt/mongodb/mongodb.yaml  
# 使用mongo連接配接執行個體  
mongo --host 10.1.1.246  
# mongodb的auth校驗非常完善,本文檔不做詳細贅述,内容實在太多了  
# 參考位址 https://docs.mongodb.com/v3.6/core/authentication/  
# 建立root角色組下的使用者 使用者名為 rsadmin 密碼123456  
use admin;  
db.createUser({user:'rsadmin', pwd:'123456', roles:['root']});  
# 該root角色組擁有管理使用者組、叢集、資料的絕大部分權限,實際生産環境中應謹慎建立  
exit 
           

auth校驗是針對資料庫層面的校驗,可以對應為mysql的使用者概念,主要是為了資料安全

而叢集間的認證也是有必要的,這裡開啟keyFile。

使用openssl指令建立key

# -base64 使用base64編碼 512代表位元組長度  
openssl rand -base64 512 >> /opt/mongodb/mongo.key  
chmod 600 /opt/mongodb/mongo.key # 修改key檔案權限
# 将建立的mongo.key複制到其他節點的相同路徑下,友善管理  
scp /opt/mongodb/mongo.key [email protected]:/opt/mongodb/  
# 其他機器ip依次替換即可
# 複制成功後需要改動mongo.key檔案的所有者 
chown mongodb:mongodb /opt/mongodb/mongo.key
           

準備工作做完,配置M6 Primary節點配置

vim /opt/mongodb/mon_rs_primary_0.yaml  
# -------------以下為配置檔案的内容--------------------  
systemLog:  
  destination: "file"  #日志使用檔案  
  path: "/var/mongodb/log/mongod.log"  #日志檔案路徑  
  logAppend: true  #允許日志追加記錄  
  component:  
    replication:  
      rollback:  
        verbosity: 5  
processManagement:  
  fork: true  #背景守護程序啟動  
  pidFilePath: "/opt/mongodb/mongod.pid"  #pid檔案路徑  
net:  
  bindIp: "10.1.1.246"  
  port: 27017  #執行個體監聽端口  
storage:  
  dbPath: "/var/mongodb/data"  #資料檔案路徑  
  directoryPerDB: false  #一個庫一個檔案此參數與系統檔案有關  
  journal:  
    enabled: true  
replication:  
  replSetName: 'rs0' # 副本集的名字,所有節點都要一緻  
security:  
  keyFile: '/opt/mongodb/mongo.key' # key檔案路徑 上一步生成的  
  clusterAuthMode: 'keyFile' # 校驗方式為keyFile  
           

配置M7、M8、M9 Secondary節點配置(與Primary節點無差別,除了IP)

vim /opt/mongodb/mon_rs_secondary_1.yaml  
# -------------以下為配置檔案的内容--------------------  
systemLog:  
  destination: "file"  #日志使用檔案  
  path: "/var/mongodb/log/mongod.log"  #日志檔案路徑  
  logAppend: true  #允許日志追加記錄  
  component:  
    replication:  
      rollback:  
        verbosity: 5  
processManagement:  
  fork: true  #背景守護程序啟動  
  pidFilePath: "/opt/mongodb/mongod.pid"  #pid檔案路徑  
net:  
  bindIp: "10.1.1.247"  
  port: 27017  #執行個體監聽端口  
storage:  
  dbPath: "/var/mongodb/data"  #資料檔案路徑  
  directoryPerDB: false  #一個庫一個檔案此參數與系統檔案有關  
  journal:  
    enabled: true  
replication:  
  replSetName: 'rs0' # 副本集的名字,所有節點都要一緻  
security:  
  keyFile: '/opt/mongodb/mongo.key' # key檔案路徑 上一步生成的  
  clusterAuthMode: 'keyFile' # 校驗方式為keyFile  
           

三台從節點機器配置除IP外完全一緻。

Arbiter 仲裁節點 M5節點配置檔案

仲裁節點與其他節點配置不同,需要建立一個專用的資料存放目錄,該目錄不存放其他節點資料,隻是存儲仲裁節點用到的資料。

# 建立仲裁節點存放資料目錄  
mkdir /var/mongodb/abr  
# 修改所有者  
chown -R mongodb:mongodb /var/mongodb  
# 編輯 仲裁節點的配置内容  
vim /opt/mongodb/mon_rs_secondary_1.yaml  
# -------------以下為配置檔案的内容--------------------  
systemLog:  
  destination: "file"  #日志使用檔案  
  path: "/var/mongodb/log/mongod.log"  #日志檔案路徑  
  logAppend: true  #允許日志追加記錄  
processManagement:  
  fork: true  #背景守護程序啟動  
  pidFilePath: "/opt/mongodb/mongod.pid"  #pid檔案路徑  
net:  
  bindIp: "10.1.1.245"  
  port: 27017  #執行個體監聽端口  
storage:  
  dbPath: "/var/mongodb/abr"  #資料檔案路徑  
  directoryPerDB: false  #一個庫一個檔案此參數與系統檔案有關  
replication:  
  replSetName: 'rs0'  
security:  
  keyFile: '/opt/mongodb/mongo.key'  
           

2.4.4 服務啟動

MongoDB服務停止的三種方式

主節點以單執行個體啟動後,需要關閉,關閉的方式用三種,

第一種是查詢pid kill結束程序,上文有介紹。這種強制停止的方式可能會導緻下次啟動不起來,需要删除data目錄下的mongod.lock檔案。

第二種,使用mongodb自帶的停止服務的方式,

在啟動服務的指令最後加上 --shutdown 參數就能正常關閉服務。

啟動指令為

sudo -u mongodb -g mongodb /opt/mongodb/bin/mongod -f /opt/mongodb/mongodb.yaml

則停止指令為

sudo -u mongodb -g mongodb /opt/mongodb/bin/mongod -f /opt/mongodb/mongodb.yaml --shutdown

第三種,使用mongo用戶端連接配接後,停止服務

mongo --host 10.1.1.246  
use admin;  
db.shutdownServer();  
           

推薦使用第二種方式

啟動主節點Primary M6節點

sudo -u mongodb -g mongodb /opt/mongodb/bin/mongod -f /opt/mongodb/mon_rs_primary_0.yaml

依次啟動M7、M8、M9 節點

sudo -u mongodb -g mongodb /opt/mongodb/bin/mongod -f /opt/mongodb/mon_rs_secondary_1.yaml

啟動仲裁節點M5

sudo -u mongodb -g mongodb /opt/mongodb/bin/mongod -f /opt/mongodb/mon_rs_arbiter_2.yaml

都啟動成功後,現有的5個節點其實誰都可以成為Primary節點,還需要在主節點上配置

任意節點使用mongo連接配接主節點服務

mongo --host 10.1.1.246  
# 因為開啟了auth校驗,現在各種指令執行都會提示未校驗,需要登入下  
use admin;  
db.auth('rsadmin', '123456');  
# 校驗成功會提示1,可以執行各種指令了  
# 副本集設定初始化  
rs.initiate()  
# 添加三個從節點  
rs.add('10.1.1.247:27017');  
rs.add('10.1.1.248:27017');  
rs.add('10.1.1.249:27017');  
# 添加仲裁節點  
rs.addArb('10.1.1.245:27017');  
# 如果添加失敗 回報的errMsg都會有提示失敗的原因  
# 添加成功後檢視狀态  
rs.status();  
# 以下為建立成功的狀态顯示  
{  
    "set" : "rs0",  
    "date" : ISODate("2019-05-09T03:08:44.242Z"),  
    "myState" : 1,  
    "term" : NumberLong(1),  
    "syncingTo" : "",  
    "syncSourceHost" : "",  
    "syncSourceId" : -1,  
    "heartbeatIntervalMillis" : NumberLong(2000),  
    "optimes" : {  
        "lastCommittedOpTime" : {  
            "ts" : Timestamp(1557371321, 1),  
            "t" : NumberLong(1)  
        },  
        "readConcernMajorityOpTime" : {  
            "ts" : Timestamp(1557371321, 1),  
            "t" : NumberLong(1)  
        },  
        "appliedOpTime" : {  
            "ts" : Timestamp(1557371321, 1),  
            "t" : NumberLong(1)  
        },  
        "durableOpTime" : {  
            "ts" : Timestamp(1557371321, 1),  
            "t" : NumberLong(1)  
        }  
    },  
    "members" : [  
        {  
            "_id" : 0,  
            "name" : "10.1.1.246:27017",  
            "health" : 1,  
            "state" : 1,  
            "stateStr" : "PRIMARY",  
            "uptime" : 1791,  
            "optime" : {  
                "ts" : Timestamp(1557371321, 1),  
                "t" : NumberLong(1)  
            },  
            "optimeDate" : ISODate("2019-05-09T03:08:41Z"),  
            "syncingTo" : "",  
            "syncSourceHost" : "",  
            "syncSourceId" : -1,  
            "infoMessage" : "",  
            "electionTime" : Timestamp(1557370530, 1),  
            "electionDate" : ISODate("2019-05-09T02:55:30Z"),  
            "configVersion" : 5,  
            "self" : true,  
            "lastHeartbeatMessage" : ""  
        },  
        {  
            "_id" : 1,  
            "name" : "10.1.1.247:27017",  
            "health" : 1,  
            "state" : 2,  
            "stateStr" : "SECONDARY",  
            "uptime" : 752,  
            "optime" : {  
                "ts" : Timestamp(1557371321, 1),  
                "t" : NumberLong(1)  
            },  
            "optimeDurable" : {  
                "ts" : Timestamp(1557371321, 1),  
                "t" : NumberLong(1)  
            },  
            "optimeDate" : ISODate("2019-05-09T03:08:41Z"),  
            "optimeDurableDate" : ISODate("2019-05-09T03:08:41Z"),  
            "lastHeartbeat" : ISODate("2019-05-09T03:08:43.694Z"),  
            "lastHeartbeatRecv" : ISODate("2019-05-09T03:08:42.804Z"),  
            "pingMs" : NumberLong(0),  
            "lastHeartbeatMessage" : "",  
            "syncingTo" : "10.1.1.246:27017",  
            "syncSourceHost" : "10.1.1.246:27017",  
            "syncSourceId" : 0,  
            "infoMessage" : "",  
            "configVersion" : 5  
        },  
        {  
            "_id" : 2,  
            "name" : "10.1.1.248:27017",  
            "health" : 1,  
            "state" : 2,  
            "stateStr" : "SECONDARY",  
            "uptime" : 270,  
            "optime" : {  
                "ts" : Timestamp(1557371321, 1),  
                "t" : NumberLong(1)  
            },  
            "optimeDurable" : {  
                "ts" : Timestamp(1557371321, 1),  
                "t" : NumberLong(1)  
            },  
            "optimeDate" : ISODate("2019-05-09T03:08:41Z"),  
            "optimeDurableDate" : ISODate("2019-05-09T03:08:41Z"),  
            "lastHeartbeat" : ISODate("2019-05-09T03:08:43.909Z"),  
            "lastHeartbeatRecv" : ISODate("2019-05-09T03:08:42.373Z"),  
            "pingMs" : NumberLong(0),  
            "lastHeartbeatMessage" : "",  
            "syncingTo" : "10.1.1.249:27017",  
            "syncSourceHost" : "10.1.1.249:27017",  
            "syncSourceId" : 3,  
            "infoMessage" : "",  
            "configVersion" : 5  
        },  
        {  
            "_id" : 3,  
            "name" : "10.1.1.249:27017",  
            "health" : 1,  
            "state" : 2,  
            "stateStr" : "SECONDARY",  
            "uptime" : 513,  
            "optime" : {  
                "ts" : Timestamp(1557371321, 1),  
                "t" : NumberLong(1)  
            },  
            "optimeDurable" : {  
                "ts" : Timestamp(1557371321, 1),  
                "t" : NumberLong(1)  
            },  
            "optimeDate" : ISODate("2019-05-09T03:08:41Z"),  
            "optimeDurableDate" : ISODate("2019-05-09T03:08:41Z"),  
            "lastHeartbeat" : ISODate("2019-05-09T03:08:43.697Z"),  
            "lastHeartbeatRecv" : ISODate("2019-05-09T03:08:42.809Z"),  
            "pingMs" : NumberLong(0),  
            "lastHeartbeatMessage" : "",  
            "syncingTo" : "10.1.1.246:27017",  
            "syncSourceHost" : "10.1.1.246:27017",  
            "syncSourceId" : 0,  
            "infoMessage" : "",  
            "configVersion" : 5  
        },  
        {  
            "_id" : 4,  
            "name" : "10.1.1.245:27017",  
            "health" : 1,  
            "state" : 7,  
            "stateStr" : "ARBITER",  
            "uptime" : 492,  
            "lastHeartbeat" : ISODate("2019-05-09T03:08:43.683Z"),  
            "lastHeartbeatRecv" : ISODate("2019-05-09T03:08:42.303Z"),  
            "pingMs" : NumberLong(0),  
            "lastHeartbeatMessage" : "",  
            "syncingTo" : "",  
            "syncSourceHost" : "",  
            "syncSourceId" : -1,  
            "infoMessage" : "",  
            "configVersion" : 5  
        }  
    ],  
    "ok" : 1,  
    "operationTime" : Timestamp(1557371321, 1),  
    "$clusterTime" : {  
        "clusterTime" : Timestamp(1557371321, 1),  
        "signature" : {  
            "hash" : BinData(0,"iEDe4wcimYrLW/cIa0ODX3dHFJY="),  
            "keyId" : NumberLong("6688855494104186883")  
        }  
    }  
}  
# 檢視目前副本集的配置  
rs.conf();  
# 以下為副本集配置内容  
{  
    "_id" : "rs0",  
    "version" : 5,  
    "protocolVersion" : NumberLong(1),  
    "members" : [  
        {  
            "_id" : 0,  
            "host" : "10.1.1.246:27017",  
            "arbiterOnly" : false,  
            "buildIndexes" : true,  
            "hidden" : false,  
            "priority" : 1,  
            "tags" : {  
                  
            },  
            "slaveDelay" : NumberLong(0),  
            "votes" : 1  
        },  
        {  
            "_id" : 1,  
            "host" : "10.1.1.247:27017",  
            "arbiterOnly" : false,  
            "buildIndexes" : true,  
            "hidden" : false,  
            "priority" : 1,  
            "tags" : {  
                  
            },  
            "slaveDelay" : NumberLong(0),  
            "votes" : 1  
        },  
        {  
            "_id" : 2,  
            "host" : "10.1.1.248:27017",  
            "arbiterOnly" : false,  
            "buildIndexes" : true,  
            "hidden" : false,  
            "priority" : 1,  
            "tags" : {  
                  
            },  
            "slaveDelay" : NumberLong(0),  
            "votes" : 1  
        },  
        {  
            "_id" : 3,  
            "host" : "10.1.1.249:27017",  
            "arbiterOnly" : false,  
            "buildIndexes" : true,  
            "hidden" : false,  
            "priority" : 1,  
            "tags" : {  
                  
            },  
            "slaveDelay" : NumberLong(0),  
            "votes" : 1  
        },  
        {  
            "_id" : 4,  
            "host" : "10.1.1.245: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("5cd396a0b36b6340a8634b62")  
    }  
}  
           

重點關注三個參數

hidden: 該參數對Secondary節點起作用,是否顯示該節點,如果該節點為true,則該節點隻參與資料的備份,有選舉權,不能成為主節點,不參與讀資料。可以作為資料的備份節點。

priority:改參數代表目前節點的權重,越大權重越高,權重的左右在于決定選舉權的順序,權重越大,則在選舉中,優先變成Primary節點,可以看到仲裁節點中該參數為0,沒有成為主節點的權利。其他節點該參數為1。

votes:決定該節點是否有選舉權,可以了解為目前節點是否有選舉Primary節點的資格。

2.4.5 資料同步測試

寫服務隻有Primaryj節點提供,連接配接主節點

已連接配接的略過此步驟

mongo --host 10.1.1.246  
use admin;  
db.auth('rsadmin', '123456');  
# 建立school 庫  
use school;  
db.createCollection('student');  
db.student.insert({name:'張三'});  
db.student.insert({name:'李四'});  
           

使用其他節點連接配接其他任意Secondary節點進行測試,這裡也需要認證,認證同Primary節點完全一緻

mongo --host 10.1.1.247  
use admin;  
db.auth("rsadmin", "123456");  
# 從節點預設不提供讀寫服務,擷取臨時授權  
rs.slaveOk(); # 該授權僅僅能擷取讀的授權,寫必須在主節點上  
use school;  
db.student.find();  
# 以下為内容  
{ "_id" : ObjectId("5cd3a12895f1c931dac32f9c"), "name" : "張三" }  
{ "_id" : ObjectId("5cd3a12d95f1c931dac32f9d"), "name" : "李四" }  
           

資料同步成功

2.4.6 故障自動恢複

1.停止主節點M6 模拟主節點故障當機

sudo -u mongodb -g mongodb /opt/mongodb/bin/mongod -f /opt/mongodb/mon_rs_primary_0.yaml --shutdown

連接配接其他任意節點:

mongo --host 10.1.1.247  
# 認證  
use admin;  
db.auth('rsadmin','123456');  
# 檢視狀态  
rs.status();  
# -------狀态-------------  
{  
    "set" : "rs0",  
    "date" : ISODate("2019-05-09T03:58:58.347Z"),  
    "myState" : 2,  
    "term" : NumberLong(2),  
    "syncingTo" : "10.1.1.249:27017",  
    "syncSourceHost" : "10.1.1.249:27017",  
    "syncSourceId" : 3,  
    "heartbeatIntervalMillis" : NumberLong(2000),  
    "optimes" : {  
        "lastCommittedOpTime" : {  
            "ts" : Timestamp(1557374332, 1),  
            "t" : NumberLong(2)  
        },  
        "readConcernMajorityOpTime" : {  
            "ts" : Timestamp(1557374332, 1),  
            "t" : NumberLong(2)  
        },  
        "appliedOpTime" : {  
            "ts" : Timestamp(1557374332, 1),  
            "t" : NumberLong(2)  
        },  
        "durableOpTime" : {  
            "ts" : Timestamp(1557374332, 1),  
            "t" : NumberLong(2)  
        }  
    },  
    "members" : [  
        {  
            "_id" : 0,  
            "name" : "10.1.1.246:27017",  
            "health" : 0,  
            "state" : 8,  
            "stateStr" : "(not reachable/healthy)",  
            "uptime" : 0,  
            "optime" : {  
                "ts" : Timestamp(0, 0),  
                "t" : NumberLong(-1)  
            },  
            "optimeDurable" : {  
                "ts" : Timestamp(0, 0),  
                "t" : NumberLong(-1)  
            },  
            "optimeDate" : ISODate("1970-01-01T00:00:00Z"),  
            "optimeDurableDate" : ISODate("1970-01-01T00:00:00Z"),  
            "lastHeartbeat" : ISODate("2019-05-09T03:58:56.955Z"),  
            "lastHeartbeatRecv" : ISODate("2019-05-09T03:44:19.236Z"),  
            "pingMs" : NumberLong(0),  
            "lastHeartbeatMessage" : "Connection refused",  
            "syncingTo" : "",  
            "syncSourceHost" : "",  
            "syncSourceId" : -1,  
            "infoMessage" : "",  
            "configVersion" : -1  
        },  
        {  
            "_id" : 1,  
            "name" : "10.1.1.247:27017",  
            "health" : 1,  
            "state" : 2,  
            "stateStr" : "SECONDARY",  
            "uptime" : 4577,  
            "optime" : {  
                "ts" : Timestamp(1557374332, 1),  
                "t" : NumberLong(2)  
            },  
            "optimeDate" : ISODate("2019-05-09T03:58:52Z"),  
            "syncingTo" : "10.1.1.249:27017",  
            "syncSourceHost" : "10.1.1.249:27017",  
            "syncSourceId" : 3,  
            "infoMessage" : "",  
            "configVersion" : 5,  
            "self" : true,  
            "lastHeartbeatMessage" : ""  
        },  
        {  
            "_id" : 2,  
            "name" : "10.1.1.248:27017",  
            "health" : 1,  
            "state" : 2,  
            "stateStr" : "SECONDARY",  
            "uptime" : 3283,  
            "optime" : {  
                "ts" : Timestamp(1557374332, 1),  
                "t" : NumberLong(2)  
            },  
            "optimeDurable" : {  
                "ts" : Timestamp(1557374332, 1),  
                "t" : NumberLong(2)  
            },  
            "optimeDate" : ISODate("2019-05-09T03:58:52Z"),  
            "optimeDurableDate" : ISODate("2019-05-09T03:58:52Z"),  
            "lastHeartbeat" : ISODate("2019-05-09T03:58:58.064Z"),  
            "lastHeartbeatRecv" : ISODate("2019-05-09T03:58:58.063Z"),  
            "pingMs" : NumberLong(0),  
            "lastHeartbeatMessage" : "",  
            "syncingTo" : "10.1.1.249:27017",  
            "syncSourceHost" : "10.1.1.249:27017",  
            "syncSourceId" : 3,  
            "infoMessage" : "",  
            "configVersion" : 5  
        },  
        {  
            "_id" : 3,  
            "name" : "10.1.1.249:27017",  
            "health" : 1,  
            "state" : 1,  
            "stateStr" : "PRIMARY",  
            "uptime" : 3527,  
            "optime" : {  
                "ts" : Timestamp(1557374332, 1),  
                "t" : NumberLong(2)  
            },  
            "optimeDurable" : {  
                "ts" : Timestamp(1557374332, 1),  
                "t" : NumberLong(2)  
            },  
            "optimeDate" : ISODate("2019-05-09T03:58:52Z"),  
            "optimeDurableDate" : ISODate("2019-05-09T03:58:52Z"),  
            "lastHeartbeat" : ISODate("2019-05-09T03:58:58.035Z"),  
            "lastHeartbeatRecv" : ISODate("2019-05-09T03:58:57.056Z"),  
            "pingMs" : NumberLong(0),  
            "lastHeartbeatMessage" : "",  
            "syncingTo" : "",  
            "syncSourceHost" : "",  
            "syncSourceId" : -1,  
            "infoMessage" : "",  
            "electionTime" : Timestamp(1557373472, 1),  
            "electionDate" : ISODate("2019-05-09T03:44:32Z"),  
            "configVersion" : 5  
        },  
        {  
            "_id" : 4,  
            "name" : "10.1.1.245:27017",  
            "health" : 1,  
            "state" : 7,  
            "stateStr" : "ARBITER",  
            "uptime" : 3506,  
            "lastHeartbeat" : ISODate("2019-05-09T03:58:58.037Z"),  
            "lastHeartbeatRecv" : ISODate("2019-05-09T03:58:56.485Z"),  
            "pingMs" : NumberLong(0),  
            "lastHeartbeatMessage" : "",  
            "syncingTo" : "",  
            "syncSourceHost" : "",  
            "syncSourceId" : -1,  
            "infoMessage" : "",  
            "configVersion" : 5  
        }  
    ],  
    "ok" : 1,  
    "operationTime" : Timestamp(1557374332, 1),  
    "$clusterTime" : {  
        "clusterTime" : Timestamp(1557374332, 1),  
        "signature" : {  
            "hash" : BinData(0,"WCV4july6HgCfPIOsSktsZKp3zI="),  
            "keyId" : NumberLong("6688855494104186883")  
        }  
    }  
}  
           

可以看到 10.1.1.246節點的狀态時不可到達,不健康的,而10.1.1.249則變成了Primary節點。

Secondary節點被選舉為Primary節點的優先權通過參數priority來控制,越大優先級越高,通過該參數可指定從節點變為主節點的順序,寫程式的時候就可以通過配置多個ip位址來實作容災,自動恢複。

節點自動恢複,重新啟動M6節點

sudo -u mongodb -g mongodb /opt/mongodb/bin/mongod -f /opt/mongodb/mon_rs_primary_0.yaml

在任意節點上登入mongo執行rs.status(); 可以看到M6機器自動變為了Secondary節點。

2.5 Sharding 分片叢集搭建

2.5.1 Sharding 分片叢集部署說明

分片是一種可以水準擴充的模式,在資料量很大時特給力,實際大規模應用一般會采用這種架構去建構。sharding分片很好的解決了單台伺服器磁盤空間、記憶體、cpu等硬體資源的限制問題,把資料水準拆分出去,降低單節點的通路壓力。每個分片都是一個獨立的資料庫,所有的分片組合起來構成一個邏輯上的完整的資料庫。是以,分片機制降低了每個分片的資料操作量及需要存儲的資料量,達到多台伺服器來應對不斷增加的負載和資料的效果。

節點說明:

分片伺服器(Shard Server)Mongodb3.6版本及之後 該節點必須是副本集

mongod 執行個體,用于存儲實際的資料塊,實際生産環境中一個 shard server 角色可由幾台機器組成一個 relica set 承擔,防止主機單點故障。這是一個獨立普通的mongod程序,儲存資料資訊。可以是一個副本集也可以是單獨的一台伺服器。

配置伺服器(Config Server)Mongodb3.4版本及之後 該節點必須是副本集

mongod 執行個體,存儲了整個 Cluster Metadata,其中包括 chunk 資訊。

這是一個獨立的mongod程序,儲存叢集和分片的中繼資料,即各分片包含了哪些資料的資訊。最先開始建立,啟用日志功能。像啟動普通的 mongod 一樣啟動

配置伺服器,指定configsvr 選項。不需要太多的空間和資源,配置伺服器的 1KB 空間相當于真實資料的 200MB。儲存的隻是資料的分布表。

路由伺服器(Route Server)

mongos執行個體,前端路由,用戶端由此接入,且讓整個叢集看上去像單一資料庫,前端應用

起到一個路由的功能,供程式連接配接。本身不儲存資料,在啟動時從配置伺服器加載叢集資訊,開啟 mongos 程序需要知道配置伺服器的位址,指定configdb選項。

官方文檔位址:https://docs.mongodb.com/v3.6/tutorial/deploy-sharded-cluster-hashed-sharding/

其它參考文檔:https://blog.51cto.com/bigboss/2160311

優點:超大資料量支援,可橫向擴充,容災性能極強,資料分片存儲有效提升磁盤讀寫瓶頸

缺點:部署難度較大、成本較高。滿足的生産環境的部署方式至少需要8台伺服器 。

備注:大規模應用一般會采用這種架構去建構

2.5.2 伺服器規劃

所有機器都已部署成單執行個體mongodb伺服器,原配置檔案為所在位置為

/opt/mongodb/mongodb.yaml,不同部署方式有不同的配置檔案。

注意:如果機器部署過其它方式的叢集,在部署前,請清空所有執行個體的data目錄,如果使用新的data路徑則不需要清除

rm /var/mongodb/data/* -rf

由于shard和config節點必須是副本集,而機器數量不夠,這裡通過配置不同端口來實作多台伺服器的模拟。

這裡的配置檔案命名格式不再遵循上述的命名格式。

機器名 ip位址-端口 配置檔案 說明
M5-27017 10.1.1.245:27017 shard1-rs-1.yaml shard1
M5-27018 10.1.1.245:27018 shard1-rs-2.yaml shard1
M5-27019 10.1.1.245:27019 shard1-rs-3.yaml shard1
M6-27017 10.1.1.246:27017 shard2-rs-1.yaml shard2
M6-27018 10.1.1.246:27018 shard2-rs-2.yaml shard2
M6-27019 10.1.1.246:27019 shard2-rs-3.yaml shard2
M7 10.1.1.247 config-rs-1.yaml config
M8 10.1.1.248 config-rs-2.yaml config
M9 10.1.1.249 mongos.yaml mongos

伺服器規劃說明:

M5節點搭建為3節點(1主2從0仲裁)的rs0副本集 作為shard1節點

M6節點搭建為3節點(1主2從0仲裁)的rs1副本集 作為 shard2節點

M7,M8搭建成2節點(1主1從0仲裁)的config副本集 作為config節點

M9 作為mongos節點 起到路由的作用。

真正的生産環境中,所用節點都為獨立伺服器,且mongos應部署多個,每個應用程式伺服器都應該部署一個mongos

2.5.3 準備工作

建立通用校驗key

# 建立通用公鑰檔案  
openssl rand -base64 512 > /opt/mongodb/mon.key  
# 修改檔案所有者  
chown -R mongodb:mongodb /opt/mongodb/mon.key  
# 修改檔案權限  
chmod -R 600 /opt/mongodb/mon.key  
# 依次複制到其他節點 
#注意:複制過去以後,該檔案的所有者為root 需要重新改成mongodb  
scp /opt/mongodb/mon.key 10.1.1.246:/opt/mongodb/  
scp /opt/mongodb/mon.key 10.1.1.247:/opt/mongodb/  
scp /opt/mongodb/mon.key 10.1.1.248:/opt/mongodb/  
scp /opt/mongodb/mon.key 10.1.1.249:/opt/mongodb/  
           

2.5.4 config副本集部署

官方推薦config的副本集生産環境上不低于3個節點,這裡隻搭建了一個2節點的config server

M7節點

# M7 節點  
# 建立資料存放目錄、日志存放目錄、修改所有者  
mkdir -p /var/mongodb/configdata  
chown -R mongodb:mongodb /var/mongodb  
  
# 配置 config-rs-1.yaml 檔案  
vim /opt/mongodb/config-rs-1.yaml  
# 内容如下  
systemLog:  
  destination: "file"  #日志使用檔案  
  path: "/var/mongodb/log/config.log"  #日志檔案路徑  
  logAppend: true  #允許日志追加記錄  
processManagement:  
  fork: true  #背景守護程序啟動  
  pidFilePath: "/opt/mongodb/config.pid"  #pid檔案路徑  
net:  
  bindIp: "0.0.0.0"  
  port: 27017  #執行個體監聽端口  
storage:  
  dbPath: "/var/mongodb/configdata"  #資料檔案路徑  
  directoryPerDB: false  #一個庫一個檔案此參數與系統檔案有關  
replication:  
  replSetName: 'config'  
security:  
  keyFile: '/opt/mongodb/mon.key'  
sharding:  
  clusterRole: 'configsvr'  
           

M8節點

# M8 節點  
# 建立資料存放目錄、日志存放目錄、修改所有者  
mkdir -p /var/mongodb/configdata  
chown -R mongodb:mongodb /var/mongodb  
# 配置 config-rs-2.yaml 檔案  
vim /opt/mongodb/config-rs-2.yaml  
# 内容如下  
systemLog:  
  destination: "file"  #日志使用檔案  
  path: "/var/mongodb/log/config.log"  #日志檔案路徑  
  logAppend: true  #允許日志追加記錄  
processManagement:  
  fork: true  #背景守護程序啟動  
  pidFilePath: "/opt/mongodb/config.pid"  #pid檔案路徑  
net:  
  bindIp: "0.0.0.0"  
  port: 27017  #執行個體監聽端口  
storage:  
  dbPath: "/var/mongodb/configdata"  #資料檔案路徑  
  directoryPerDB: false  #一個庫一個檔案此參數與系統檔案有關  
replication:  
  replSetName: 'config'  
security:  
  keyFile: '/opt/mongodb/mon.key'  
sharding:  
  clusterRole: 'configsvr'  
           

啟動M7、M8上的服務

# 分别在M7、M8節點啟動服務  
sudo -u mongodb -g mongodb /opt/mongodb/bin/mongod -f /opt/mongodb/config-rs-1.yaml  
sudo -u mongodb -g mongodb /opt/mongodb/bin/mongod -f /opt/mongodb/config-rs-2.yaml  
           

配置config副本集

# 連接配接M7 或者M8  
mongo  
# 初始化config副本集  
rs.initiate({  
  _id: "config",  
  configsvr: true,  
  version: 1,  
  protocolVersion: 1,  
  writeConcernMajorityJournalDefault: true,  
  members: [  
    {  
      _id: 0,  
      host: "10.1.1.247:27017",  
      arbiterOnly: false,  
      buildIndexes: true,  
      hidden: false,  
      priority: 66,  
      tags: {},  
      slaveDelay: 0,  
      votes: 1  
    },  
    {  
      _id: 1,  
      host: "10.1.1.248:27017",  
      arbiterOnly: false,  
      buildIndexes: true,  
      hidden: false,  
      priority: 55,  
      tags: {},  
      slaveDelay: 0,  
      votes: 1  
    }  
  ],  
  settings: {  
    chainingAllowed : true,  
  }  
});  
# 會提示ok:1的字樣 通過rs.status() 檢視實際運作情況  
           

2.5.5 shard1副本集部署

# shard1 副本集配置  
# 建立資料存放目錄、日志存放目錄、修改所有者  
mkdir -p /var/mongodb/data27017  
mkdir -p /var/mongodb/data27018  
mkdir -p /var/mongodb/data27019  
chown -R mongodb:mongodb /var/mongodb  
  
# 配置 shard1-rs-1.yaml 檔案  
vim /opt/mongodb/shard1-rs-1.yaml  
# 内容如下  
systemLog:  
  destination: "file"  #日志使用檔案  
  path: "/var/mongodb/log/shard1-rs1.log"  #日志檔案路徑  
  logAppend: true  #允許日志追加記錄  
processManagement:  
  fork: true  #背景守護程序啟動  
  pidFilePath: "/opt/mongodb/shard1-rs1.pid"  #pid檔案路徑  
net:  
  bindIp: "0.0.0.0"  
  port: 27017  #執行個體監聽端口  
storage:  
  dbPath: "/var/mongodb/data27017"  #資料檔案路徑  
  directoryPerDB: false  #一個庫一個檔案此參數與系統檔案有關  
replication:  
  replSetName: 'shard1'  
security:  
  keyFile: '/opt/mongodb/mon.key'  
sharding:  
  clusterRole: 'shardsvr'  
# 配置 shard1-rs-2.yaml 檔案  
vim /opt/mongodb/shard1-rs-2.yaml  
# 内容如下  
systemLog:  
  destination: "file"  #日志使用檔案  
  path: "/var/mongodb/log/shard1-rs2.log"  #日志檔案路徑  
  logAppend: true  #允許日志追加記錄  
processManagement:  
  fork: true  #背景守護程序啟動  
  pidFilePath: "/opt/mongodb/shard1-rs2.pid"  #pid檔案路徑  
net:  
  bindIp: "0.0.0.0"  
  port: 27018  #執行個體監聽端口  
storage:  
  dbPath: "/var/mongodb/data27018"  #資料檔案路徑  
  directoryPerDB: false  #一個庫一個檔案此參數與系統檔案有關  
replication:  
  replSetName: 'shard1'  
security:  
  keyFile: '/opt/mongodb/mon.key'  
sharding:  
  clusterRole: 'shardsvr'  
  # 配置 shard1-rs-3.yaml 檔案  
vim /opt/mongodb/shard1-rs-3.yaml  
# 内容如下  
systemLog:  
  destination: "file"  #日志使用檔案  
  path: "/var/mongodb/log/shard1-rs3.log"  #日志檔案路徑  
  logAppend: true  #允許日志追加記錄  
processManagement:  
  fork: true  #背景守護程序啟動  
  pidFilePath: "/opt/mongodb/shard1-rs3.pid"  #pid檔案路徑  
net:  
  bindIp: "0.0.0.0"  
  port: 27019  #執行個體監聽端口  
storage:  
  dbPath: "/var/mongodb/data27019"  #資料檔案路徑  
  directoryPerDB: false  #一個庫一個檔案此參數與系統檔案有關  
replication:  
  replSetName: 'shard1'  
security:  
  keyFile: '/opt/mongodb/mon.key'  
sharding:  
  clusterRole: 'shardsvr'  
 
# 啟動三個服務  
sudo -u mongodb -g mongodb /opt/mongodb/bin/mongod -f /opt/mongodb/shard1-rs-1.yaml  
sudo -u mongodb -g mongodb /opt/mongodb/bin/mongod -f /opt/mongodb/shard1-rs-2.yaml  
sudo -u mongodb -g mongodb /opt/mongodb/bin/mongod -f /opt/mongodb/shard1-rs-3.yaml  

# 連接配接27017  
mongo  

# 初始化shard1副本集  
rs.initiate({  
  _id: "shard1",  
  version: 1,  
  protocolVersion: 1,  
  writeConcernMajorityJournalDefault: true,  
  members: [  
    {  
      _id: 0,  
      host: "10.1.1.245:27017",  
      arbiterOnly: false,  
      buildIndexes: true,  
      hidden: false,  
      priority: 66,  
      tags: {  
          
      },  
      slaveDelay: 0,  
      votes: 1  
    },  
    {  
      _id: 1,  
      host: "10.1.1.245:27018",  
      arbiterOnly: false,  
      buildIndexes: true,  
      hidden: false,  
      priority: 55,  
      tags: {  
          
      },  
      slaveDelay: 0,  
      votes: 1  
    },  
    {  
      _id: 2,  
      host: "10.1.1.245:27019",  
      arbiterOnly: false,  
      buildIndexes: true,  
      hidden: false,  
      priority: 33,  
      tags: {  
          
      },  
      slaveDelay: 0,  
      votes: 1  
    }  
  ],  
  settings: {  
    chainingAllowed : true,  
  }  
});  
# 提示 { "ok" : 1 } 則設定成功,通過rs.status() 檢視實際運作情況  
           

備注:

  1. 目前運作的副本集是沒有讀寫執行權限的,分片搭建成功後最後在建立一個使用者來操作
  2. 綁定0.0.0.0以後,通過127.0.0.1的位址登入的使用者操作權限略大于通過10.1.1.245的使用者,可以執行副本集初始化操作
  3. 副本集的設定有兩種方式,一種是2.4章節中所使用的通過rs.add方法的方式添加從節點,哪個節點發起添加從節點的動作,哪個節點就自動變為主節點,該方式要求使用者要有較高的權限,而未添加使用者之前,通過127.0.0.1登入的使用者也沒有add的權限,為了減少操作,這裡采用初始化時即配置節點的方式。該配置方式通過priority參數的大小指定端口27017的服務為Primary節點。

2.5.6 shard2副本集部署

将2.5.4中的所有内容中的shard1關鍵字替換為shard2 位址修改為10.1.1.246即可

與M5節點的搭建方式完全一緻,過程略過,如果搭建不出來,You may not be able to make a living by programming.

2.5.7 mongos節點部署

建立mongos資料存放目錄 更改目錄所有者

mkdir -p /var/mongodb/route  
chown -R mongodb:mongodb /var/mongodb  
           

建立mongos節點的配置檔案

# ----------以下為配置檔案内容------------------  
systemLog:  
  destination: "file"  #日志使用檔案  
  path: "/var/mongodb/log/route.log"  #日志檔案路徑  
  logAppend: true  #允許日志追加記錄  
processManagement:  
  fork: true  #背景守護程序啟動  
  pidFilePath: "/opt/mongodb/mongos.pid"  #pid檔案路徑  
net:  
  bindIp: "0.0.0.0"  
  port: 27017  #執行個體監聽端口  
sharding:  
  configDB: "config/10.1.1.247:27017,10.1.1.248:27017"  
security:  
  keyFile: '/opt/mongodb/mon.key'  
           

2.5.8 服務啟動

shard1、shard2、config三個副本集已啟動,這裡就是把三個副本集聯系到一起。

開啟mongos服務

注意:這裡是作為路由節點 啟動的指令是mongos不是mongod

sudo -u mongodb -g mongodb /opt/mongodb/bin/mongos -f /opt/mongodb/mongos.yaml  
# 登入shell  
mongo  
# 建立高權限使用者 root 123456  
use admin;  
db.createUser({user: "root",pwd: "123456",roles: ['__system']});  
exit # 建立成功後退出  
# 重新連接配接  
mongo  
use admin;  
db.auth("root", '123456');  
# 添加分片伺服器  
sh.addShard("shard1/10.1.1.245:27017,10.1.1.245:27018,10.1.1.245:27019");  
sh.addShard("shard2/10.1.1.246:27017,10.1.1.246:27018,10.1.1.246:27019");  
# 會提示 "shardAdded" : "shard2","ok" : 1類似字樣 成功  
sh.status(); # 檢視目前叢集狀态  
# 為了測試分片效果,修改分片大小  
# 修改分片大小為1M 預設為64M  
use config;  
db.settings.save({_id:"chunksize",value:1});  
use school;  
db.createCollection('student');  
# 對庫和student集合使用分片,片鍵為age 方式為 1  
sh.enableSharding('school');  
sh.shardCollection("school.student",{'age':1});  
# 插入2w條資料  
for (i = 1; i <= 20000; i++) db.student.insert({age:(i%100), name:"學生"+i, address:i+"遼甯", country:"中國", course:"cousre"+"(i%12)"});  
# 檢視分片結果  
sh.status();  
           

如上圖所示,根據片鍵age升序分片成功

片鍵選擇:

官網文檔:https://docs.mongodb.com/v3.6/core/sharding-shard-key/

https://docs.mongodb.com/v3.6/sharding/#sharding-strategy

其他文檔: http://mongoing.com/understand-mongodb-shardkey

http://www.mongoing.com/blog/post/on-selecting-a-shard-key-for-mongodb

片鍵的分片方式有四種:

1:升序,-1降序,hashed:哈希分布, 還有一種遠端分片政策,這裡不做詳細贅述。

原創,轉載請注明來源。