1. 環境准備
在Mongo的官網下載Linux版本安裝包,然后解壓到對應的目錄下;由於資源有限,我們采用Replica Sets + Sharding方式來配置高可用。結構圖如下所示:
這里我說明下這個圖所表達的意思:
Shard服務器:使用Replica Sets確保每個數據節點都具有備份、自動容錯轉移、自動恢復的能力。
- 配置服務器:使用3個配置服務器確保元數據完整性。
- 路由進程:使用3個路由進程實現平衡,提高客戶端接入性能
- 副本集1:Shard11,Shard12,Shard13組成一個副本集,提供Sharding中shard1的功能;
- 副本集2:Shard21,Shard22,Shard23組成一個副本集,提供Sharding中shard2的功能;
- 副本集3:Shard31,Shard32,Shard33組成一個副本集,提供Sharding中shard3的功能;
- 3個配置服務器進程和3個路由器進程。
- Arbiter仲裁者,是副本集中的一個MongoDB實例, 它並不保存數據。仲裁節點使用最小的資源並且不要求硬件設備。為了確保復制集中有奇數的投票成員(包括primary),需要添加仲裁節點作為投票,否則primary不能運行時不會自動切換primary。
構建一個mongoDB Sharding Cluster需要三種角色:shard服務器(ShardServer)、配置服務器(config Server)、路由進程(Route Process)
Shard 服務器
Shard服務器即存儲實際數據的分片,每個shard可以是一個mongod實例,也可以是一組mongod實例構成的Replica Sets。為了實現每個Shard內部的故障自動轉換,MongoDB官方建議每個shard為一組Replica Sets。
配置服務器
為了將一個特定的collection存儲在多個shard中,需要為該collection指定一個shard key,決定該條記錄屬於哪個chunk,配置服務器可以存儲以下信息,每個shard節點的配置信息,每個chunk的shard key范圍,chunk在各shard的分布情況,集群中所有DB和collection的sharding配置信息。
路由進程
它是一個前段路由,客戶端由此接入,首先詢問配置服務器需要到哪個shard上查詢或保存記錄,然后連接相應的shard執行操作,最后將結果返回給客戶端,客戶端只需要將原本發給mongod的查詢或更新請求原封不動地發給路由進程,而不必關心所操作的記錄存儲在哪個shard上。
按照架構圖,理論上是需要15台機器的,由於資源有限,用目錄來替代物理機,下面給出配置表格:
192.168.187.201 |
192.168.187.202 |
192.168.187.203 |
Shard11:10011 主節點 |
Shard12:10012 副節點 |
Shard13:10013 仲裁點 |
Shard21:10021 仲裁點 |
Shard22:10022 主節點 |
Shard32:10023 副節點 |
Shard31:10031 副節點 |
Shard32:10032 仲裁點 |
Shard33:10033 主節點 |
ConfigSvr:10041 |
ConfigSvr:10042 |
ConfigSvr:10043 |
Mongos:10051 |
Mongos:10052 |
Mongos:10053 |
2. 配置Shard + Replica Sets
2.1系統配置
Linux操作系統參數
系統全局允許分配的最大文件句柄數:
sysctl -w fs.file-max=2097152
sysctl -w fs.nr_open=2097152
echo 2097152 > /proc/sys/fs/nr_open
允許當前會話/進程打開文件句柄數:
ulimit -n 1048576
修改 ‘fs.file-max’ 設置到 /etc/sysctl.conf 文件:
fs.file-max = 1048576
修改/etc/security/limits.conf 持久化設置允許用戶/進程打開文件句柄數
* soft nofile 1048576
* hard nofile 1048576
* soft nproc 524288
* hard nproc 524288
TCP 協議棧網絡參數
並發連接 backlog 設置:
sysctl -w net.core.somaxconn=32768
sysctl -w net.ipv4.tcp_max_syn_backlog=16384
sysctl -w net.core.netdev_max_backlog=16384
可用知名端口范圍:
sysctl -w net.ipv4.ip_local_port_range=80 65535'
TCP Socket 讀寫 Buffer 設置:
sysctl -w net.core.rmem_default=262144
sysctl -w net.core.wmem_default=262144
sysctl -w net.core.rmem_max=16777216
sysctl -w net.core.wmem_max=16777216
sysctl -w net.core.optmem_max=16777216
sysctl -w net.ipv4.tcp_rmem='1024 4096 16777216'
sysctl -w net.ipv4.tcp_wmem='1024 4096 16777216'
TCP 連接追蹤設置(Centos7以下才有,以上版本則不用):
sysctl -w net.nf_conntrack_max=1000000
sysctl -w net.netfilter.nf_conntrack_max=1000000
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=30
2.2 安裝
統一分別在三台機器的/opt/app/mongoCluster369部署mongodb集群。
在linux官網下載mongodb的安裝包,目前所用安裝包為:mongodb-linux-x86_64-rhel70-3.6.9.tgz
現在以192.168.31.231機器上操作為例:
使用命令tar -zxvf mongodb-linux-x86_64-rhel70-3.6.9.tgz 解壓mongodb
解壓后查看如下:
把mongodb-linux-x86_64-rhel70-3.6.9移動到指定目錄,當前指定目錄為/opt/app/,並改名為mongodb
在該台機器上mongodbCluster369目錄中建立conf(配置文件)、mongos(路由)、config(配置)、shard1、shard2、shard3(三個切片)六個目錄,因為mongos不存儲數據,只需要建立日志文件即可。
mkdir -p /opt/app/mongodbCluster369/conf
mkdir -p /opt/app/mongodbCluster369/mongos/log
mkdir -p /opt/app/mongodbCluster369/mongos/pid
mkdir -p /opt/app/mongodbCluster369/config/data
mkdir -p /opt/app/mongodbCluster369/config/log
mkdir -p /opt/app/mongodbCluster369/config/pid
mkdir -p /opt/app/mongodbCluster369/shard1/data
mkdir -p /opt/app/mongodbCluster369/shard1/log
mkdir -p /opt/app/mongodbCluster369/shard1/pid
mkdir -p /opt/app/mongodbCluster369/shard2/data
mkdir -p /opt/app/mongodbCluster369/shard2/log
mkdir -p /opt/app/mongodbCluster369/shard2/pid
mkdir -p /opt/app/mongodbCluster369/shard3/data
mkdir -p /opt/app/mongodbCluster369/shard3/log
mkdir -p /opt/app/mongodbCluster369/shard3/pid
配置環境變量
vi /etc/profile
並添加如下內容:
export MONGODB_HOME=/opt/app/mongodb
export PATH=$PATH:$MONGODB_HOME/bin
source /etc/profile
使立即生效
2.3 配置分片副本集
設置第一個分片副本集
配置文件
vi /opt/app/mongodbCluster369/conf/shard1.conf
配置文件內容為:
#配置文件內容
systemLog: destination: file path: /opt/app/mongodbCluster369/shard1/log/shard1.log logAppend: true processManagement: fork: true pidFilePath: /opt/app/mongodbCluster369/shard1/pid/shard1.pid net: bindIp: 192.168.187.201 port: 10011 maxIncomingConnections: 20000 storage: dbPath: /opt/app/mongodbCluster369/shard1/data journal: enabled: true commitIntervalMs: 500 directoryPerDB: true syncPeriodSecs: 300 engine: wiredTiger wiredTiger: engineConfig: cacheSizeGB: 103 statisticsLogDelaySecs: 0 journalCompressor: snappy directoryForIndexes: false collectionConfig: blockCompressor: snappy indexConfig: prefixCompression: true replication: oplogSizeMB: 10000 replSetName: shard1 sharding: clusterRole: shardsvr
設置第二個分片副本集
vi /opt/app/mongodbCluster369/conf/shard2.conf
# 配置文件內容
systemLog: destination: file path: /opt/app/mongodbCluster369/shard2/log/shard2.log logAppend: true processManagement: fork: true pidFilePath: /opt/app/mongodbCluster369/shard2/pid/shard2.pid net: bindIp: 192.168.187.201 port: 10021 maxIncomingConnections: 20000 storage: dbPath: /opt/app/mongodbCluster369/shard2/data journal: enabled: true commitIntervalMs: 500 directoryPerDB: true syncPeriodSecs: 300 engine: wiredTiger wiredTiger: engineConfig: cacheSizeGB: 103 statisticsLogDelaySecs: 0 journalCompressor: snappy directoryForIndexes: false collectionConfig: blockCompressor: snappy indexConfig: prefixCompression: true replication: oplogSizeMB: 10000 replSetName: shard2 sharding: clusterRole: shardsvr
設置第三個分片副本集
vi /opt/app/mongodbCluster369/conf/shard3.conf
# 配置文件內容
systemLog: destination: file path: /opt/app/mongodbCluster369/shard3/log/shard3.log logAppend: true processManagement: fork: true pidFilePath: /opt/app/mongodbCluster369/shard3/pid/shard3.pid net: bindIp: 192.168.187.201 port: 10031 maxIncomingConnections: 20000 storage: dbPath: /opt/app/mongodbCluster369/shard3/data journal: enabled: true commitIntervalMs: 500 directoryPerDB: true syncPeriodSecs: 300 engine: wiredTiger wiredTiger: engineConfig: cacheSizeGB: 103 statisticsLogDelaySecs: 0 journalCompressor: snappy directoryForIndexes: false collectionConfig: blockCompressor: snappy indexConfig: prefixCompression: true replication: oplogSizeMB: 10000 replSetName: shard3 sharding: clusterRole: shardsvr
2.4 config server配置服務器
vi /opt/app/mongodbCluster369/conf/config.conf
# 配置文件內容
systemLog: destination: file path: /opt/app/mongodbCluster369/config/log/config.log logAppend: true processManagement: fork: true pidFilePath: /opt/app/mongodbCluster369/config/pid/config.pid net: bindIp: 192.168.187.201 port: 10041 maxIncomingConnections: 20000 storage: dbPath: /opt/app/mongodbCluster369/config/data journal: enabled: true commitIntervalMs: 500 directoryPerDB: true syncPeriodSecs: 300 engine: wiredTiger replication: oplogSizeMB: 10000 replSetName: configs sharding: clusterRole: configsvr
2.5 配置路由服務器mongos
vi /opt/app/mongodbCluster369/conf/mongos.conf
# 配置文件內容
systemLog: destination: file path: /opt/app/mongodbCluster369/mongos/log/mongos.log logAppend: true processManagement: fork: true pidFilePath: /opt/app/mongodbCluster369/mongos/pid/mongos.pid net: bindIp: 192.168.187.201 port: 10051 maxIncomingConnections: 20000 sharding: configDB: configs/192.168.187.201:10041,192.168.187.202:10042,192.168.187.203:10043
參數說明:
dbpath:數據存放目錄
logpath:日志存放路徑
pidfilepath:進程文件,方便停止mongodb
logappend:以追加的方式記錄日志
directoryperdb:為每一個數據庫按照數據庫名建立文件夾
replSet:replica set的名字
bindIp:mongodb所綁定的ip地址
port:mongodb進程所使用的端口號,默認為27017
fork:以后台方式運行進程
oplogSize:mongodb操作日志文件的最大大小。單位為Mb,默認為硬盤剩余空間的5%
shardsvr:分片節點
configsvr:配置服務節點
configdb:配置config節點到route節點
journal:寫日志
smallfiles:當提示空間不夠時添加此參數
noprealloc:預分配方式,使用預分配方式來保證寫入性能的穩定,預分配在后台運行,並且每個預分配的文件都用0進行填充。這會讓MongoDB始終保持額外的空間和空余的數據文件,從而避免了數據增長過快而帶來的分配磁盤空間引起的阻塞。設置noprealloc=true來禁用預分配的數據文件,會縮短啟動時間,但在正常操作過程中,可能會導致性能顯著下降。
2.6 分別把/opt/app/mongodb安裝包和/opt/app/mongodbCluster369配置信息復制到其他兩台機器上
使用命令scp -r /opt/app/mongodb root@192.168.187.202:/opt/app 復制mongodb到第二節點:
使用命令scp -r /opt/app/mongodbCluster369 root@192.168.187.202:/opt/app復制mongodbCluster369集群信息到第二節點:
使用root用戶登錄192.168.187.202第二節點,
然后配置環境變量
vi /etc/profile
並添加如下內容:
export MONGODB_HOME=/opt/app/mongodb
export PATH=$PATH:$MONGODB_HOME/bin
source /etc/profile
使立即生效
cd /opt/app/mongodbCluster369/conf修改切片、副本集、配置、路由5個配置文件里面的IP和端口:
Shard1.conf修改ip:
Shard2.conf修改ip:
Shard3.conf修改ip:
Config.conf修改ip:
Mongos.conf修改ip:
使用命令scp -r /opt/app/mongodb root@192.168.187.203:/opt/app 復制mongodb到第三節點:
使用命令scp -r /opt/app/mongodbCluster369 root@192.168.187.203:/opt/app復制mongodbCluster369集群信息到第三節點:
使用root用戶登錄192.168.187.203第三節點,
然后配置環境變量
vi /etc/profile
並添加如下內容:
export MONGODB_HOME=/opt/app/mongodb
export PATH=$PATH:$MONGODB_HOME/bin
source /etc/profile
使立即生效
cd /opt/app/mongodbCluster369/conf中修改切片、副本集、配置、路由5個配置文件里面的IP和端口:
Shard1.conf修改ip:
Shard2.conf修改ip:
Shard3.conf修改ip:
Config.conf修改ip:
Mongos.conf修改ip:
2.7 啟動mongodb集群
先啟動配置服務器和分片服務器,后啟動路由實例(三台服務器)。
2.7.1啟動配置服務器
啟動三台服務器的config server
進入mongodb的安裝包目錄/opt/app/mongodb,使用如下命令啟動:
cd /opt/app/mongodb/bin
./mongod -f /opt/app/mongodbCluster369/conf/config.conf
登錄任意一台服務器,初始化配置副本集
登錄連接命令:./mongo 192.168.187.201:10041/admin
配置如下內容:
> config = {
... _id : "configs",
... members : [
... {_id : 0, host : "192.168.187.201:10041"},
... {_id : 1, host : "192.168.187.202:10042"},
... {_id : 2, host : "192.168.187.203:10043"}
... ]
... }
初始化副本集
> rs.initiate(config)
其中,“_id” : “configs” 應與配置文件中配置的replSet一致,“members”中的“host”為三個節點的ip和port
2.7.2 啟動分片服務器
l 啟動三台服務器的shard1 server
進入mongodb的安裝包目錄/opt/app/mongodb,使用如下命令啟動:
cd /opt/app/mongodb/bin
./mongod -f /opt/app/mongodbCluster369/conf/shard1.conf
登錄192.168.187.201一台服務器(192.168.187.203設置為仲裁節點,不能使用該節點登錄),初始化分片副本集
登錄連接命令:./mongo 192.168.187.201:10011/admin
配置如下內容:
> config = {
... _id : "shard1",
... members : [
... {_id : 0, host : "192.168.187.201:10011",priority:2},
... {_id : 1, host : "192.168.187.202:10012",priority:1},
... {_id : 2, host : "192.168.187.203:10013", arbiterOnly : true}
... ]
... }
初始化副本集
> rs.initiate(config)
第三個節點的“arbiterOnly”:true代表其為仲裁節點。
使用exit命令退出mongo的shell操作界面
l 啟動三台服務器的shard2 server
進入mongodb的安裝包目錄/opt/app/mongodb,使用如下命令啟動:
cd /opt/app/mongodb/bin
./mongod -f /opt/app/mongodbCluster369/conf/shard2.conf
登錄192.168.187.202一台服務器(因為192.168.187.201設置為仲裁節點,不能使用該節點登錄),初始化分片副本集
登錄連接命令:./mongo 192.168.187.202:10022/admin
配置如下內容:
> config = {
... _id : "shard2",
... members : [
... {_id : 0, host : "192.168.187.201:10021", arbiterOnly : true },
... {_id : 1, host : "192.168.187.202:10022",priority:2},
... {_id : 2, host : "192.168.187.203:10023",priority:1}
... ]
... }
初始化副本集
> rs.initiate(config)
第一個節點的“arbiterOnly”:true代表其為仲裁節點。
使用exit命令退出mongo的shell操作界面
l 啟動三台服務器的shard3 server
進入mongodb的安裝包目錄/opt/app/mongodb,使用如下命令啟動:
cd /opt/app/mongodb/bin
./mongod -f /opt/app/mongodbCluster369/conf/shard3.conf
登錄192.168.187.201一台服務器(192.168.187.202設置為仲裁節點,不能使用該節點登錄),初始化分片副本集
登錄連接命令:./mongo 192.168.187.201:10031/admin
配置如下內容:
> config = {
... _id : "shard3",
... members : [
... {_id : 0, host : "192.168.187.201:10031",priority:1},
... {_id : 1, host : "192.168.187.202:10032", arbiterOnly : true },
... {_id : 2, host : "192.168.187.203:10033",priority:2}
... ]
... }
初始化副本集
> rs.initiate(config)
第二個節點的“arbiterOnly”:true代表其為仲裁節點。
使用exit命令退出mongo的shell操作界面
2.7.3啟動路由實例
啟動三台服務器的mongos server
使用如下命令
進入mongodb的安裝包目錄/opt/app/mongodb,使用如下命令啟動:
cd /opt/app/mongodb/bin
./mongos -f /opt/app/mongodbCluster369/conf/mongos.conf
2.8 啟用分片
目前搭建了mongodb配置服務器、路由服務器、各個分片服務器,不過應用程序連接到mongos路由服務器並不能使用分片機制,還需要在程序里設置分片配置,讓分片生效。
登錄任意一台mongos,這里以192.168.187.201:10051為例:
登錄連接命令:./mongo 192.168.187.201:10051/admin
配置如下內容,串聯路由服務器與切片副本集:
sh.addShard("shard1/192.168.187.201:10011,192.168.187.202:10012,192.168.187.203:10013")
sh.addShard("shard2/192.168.187.201:10021,192.168.187.202:10022,192.168.187.203:10023")
sh.addShard("shard3/192.168.187.201:10031,192.168.187.202:10032,192.168.187.203:10033")
查看集群狀態:
sh.status()
2.9 指定數據庫與集合分片生效
目前配置服務、路由服務、分片服務、副本集服務都已經串聯起來了,但是我們的目的是希望插入數據、數據能夠自動分片。連接在mongos上,准備讓指定的數據庫、指定的集合分片生效。
接着上面2.6的步驟,不用退出mongos的操作界面
指定數據庫分片生效:
db.runCommand({enablesharding : "testdb"})
指定數據庫里需要分片的集合collection和片鍵,一般是_id:
db.runCommand({shardcollection : "testdb.table1", key : {id : "hashed"}})
我們設置testdb的table1表需要分片,根據id自動分片到shard1、shard2、shard3上面去。要這樣設置是因為不是所有mongodb的數據庫和表都需要分片!
2.10 測試分片配置結果
登錄任意一台mongos,這里以192.168.187.201:10051為例:
登錄連接命令:./mongo 192.168.187.201:10051/admin
切換數據庫:
use testdb
輸入如下命令:
for (var i = 1; i <= 5000; i++){ db.table1.insert({id:i,text:"hello world"}) }
查看分配狀態:
db.table1.stats()
如下圖所示:shard1總數:1664條
Shard2總數:1684條
Shard3總數:1652條
可以看到數據分到3個分片。已經成功了。
3. 后期運維
mongodbd的啟動順序是,先啟動配置服務器,再啟動分片,最后啟動mongos。
mongod -f /opt/app/mongodbCluster369/conf/config.conf
mongod -f /opt/app/mongodbCluster369/conf/shard1.conf
mongod -f /opt/app/mongodbCluster369/conf/shard2.conf
mongod -f /opt/app/mongodbCluster369/conf/shard3.conf
mongos -f /opt/app/mongodbCluster369/conf/mongos.conf
關閉時,直接killall殺掉所有進程
killall mongod
killall mongos
4. 問題發現:
問題一:--maxConnx過高
這與linux默認進程能打開最大文件數有關,可以通過ulimit解決.mongodb最大連接是20000
解決:ulimit -n 30000
問題二:報錯is not electable under the new configuration version 1
解決:如果你設置的第一個節點是仲裁節點的話,那么設置登錄設置節點狀態的哪個客戶端不能是仲裁節點,簡單做法 換一個節點
參考資料:
http://www.ityouknow.com/mongodb/2017/08/05/mongodb-cluster-setup.html
https://www.cnblogs.com/smartloli/p/4305739.html
https://blog.csdn.net/caofeiliju/article/details/80193997
mongodb副本+分片集群添加用戶認證密碼
https://blog.csdn.net/uncle_david/article/details/78713551
http://www.mongoing.com/docs/tutorial/convert-secondary-into-arbiter.html (從節點切換仲裁節點)