一、架構簡介
目標
單機搭建mongodb分布式集群(副本集 + 分片集群),演示mongodb分布式集群的安裝部署、簡單操作。
說明
在同一個vm啟動由兩個分片組成的分布式集群,每個分片都是一個PSS(Primary-Secondary-Secondary)模式的數據副本集;
Config副本集采用PSS(Primary-Secondary-Secondary)模式。
二、配置說明
- 端口通訊
當前集群中存在shard、config、mongos共12個進程節點,端口矩陣編排如下:
|編號|實例類型|監聽端口|
|-|-|
|1|mongos|25001|
|2|mongos|25002|
|3|mongos|25003|
|4|config|26001|
|5|config|26002|
|6|config|26003|
|7|shard1|27001|
|8|shard1|27002|
|9|shard1|27003|
|10|shard2|27004|
|11|shard2|27005|
|12|shard2|27006|
-
內部鑒權
節點間鑒權采用keyfile方式實現鑒權,mongos與分片之間、副本集節點之間共享同一套keyfile文件。 官方說明 -
賬戶設置
管理員賬戶:admin/Admin@01,具有集群及所有庫的管理權限
應用賬號:appuser/AppUser@01,具有appdb的owner權限
關於初始化權限
keyfile方式默認會開啟鑒權,而針對初始化安裝的場景,Mongodb提供了localhost-exception機制,
可以在首次安裝時通過本機創建用戶、角色,以及副本集初始操作。
三、准備工作
1. 下載安裝包
官方地址:https://www.mongodb.com/download-center
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-3.6.3.tgz
2. 部署目錄
解壓壓縮文件,將bin目錄拷貝到目標路徑/opt/local/mongo-cluster,參考以下命令:
tar -xzvf mongodb-linux-x86_64-rhel70-3.6.3.tgz
mkdir -p /opt/local/mongo-cluster
cp -r mongodb-linux-x86_64-rhel70-3.6.3/bin /opt/local/mongo-cluster
3. 創建配置文件
cd /opt/local/mongo-cluster
mkdir conf
A. mongod 配置文件 mongo_node.conf
mongo_node.conf 作為mongod實例共享的配置文件,內容如下:
storage:
engine: wiredTiger
directoryPerDB: true
journal:
enabled: true
systemLog:
destination: file
logAppend: true
operationProfiling:
slowOpThresholdMs: 10000
replication:
oplogSizeMB: 10240
processManagement:
fork: true
net:
http:
enabled: false
security:
authorization: "enabled"
選項說明可參考這里
B. mongos 配置文件 mongos.conf
systemLog:
destination: file
logAppend: true
processManagement:
fork: true
net:
http:
enabled: false
4. 創建keyfile文件
cd /opt/local/mongo-cluster
mkdir keyfile
openssl rand -base64 756 > mongo.key
chmod 400 mongo.key
mv mongo.key keyfile
mongo.key 采用隨機算法生成,用作節點內部通訊的密鑰文件
5. 創建節點目錄
WORK_DIR=/opt/local/mongo-cluster
mkdir -p $WORK_DIR/nodes/config/n1/data
mkdir -p $WORK_DIR/nodes/config/n2/data
mkdir -p $WORK_DIR/nodes/config/n3/data
mkdir -p $WORK_DIR/nodes/shard1/n1/data
mkdir -p $WORK_DIR/nodes/shard1/n2/data
mkdir -p $WORK_DIR/nodes/shard1/n3/data
mkdir -p $WORK_DIR/nodes/shard2/n1/data
mkdir -p $WORK_DIR/nodes/shard2/n2/data
mkdir -p $WORK_DIR/nodes/shard2/n3/data
mkdir -p $WORK_DIR/nodes/mongos/n1
mkdir -p $WORK_DIR/nodes/mongos/n2
mkdir -p $WORK_DIR/nodes/mongos/n3
以config 節點1 為例,nodes/config/n1/data是數據目錄,而pid文件、日志文件都存放於n1目錄
以mongos 節點1 為例,nodes/mongos/n1 存放了pid文件和日志文件
四、搭建集群
1. Config副本集
按以下腳本啟動3個Config實例
WORK_DIR=/opt/local/mongo-cluster
KEYFILE=$WORK_DIR/keyfile/mongo.key
CONFFILE=$WORK_DIR/conf/mongo_node.conf
MONGOD=$WORK_DIR/bin/mongod
$MONGOD --port 26001 --configsvr --replSet configReplSet --keyFile $KEYFILE --dbpath $WORK_DIR/nodes/config/n1/data --pidfilepath $WORK_DIR/nodes/config/n1/db.pid --logpath $WORK_DIR/nodes/config/n1/db.log --config $CONFFILE
$MONGOD --port 26002 --configsvr --replSet configReplSet --keyFile $KEYFILE --dbpath $WORK_DIR/nodes/config/n2/data --pidfilepath $WORK_DIR/nodes/config/n2/db.pid --logpath $WORK_DIR/nodes/config/n2/db.log --config $CONFFILE
$MONGOD --port 26003 --configsvr --replSet configReplSet --keyFile $KEYFILE --dbpath $WORK_DIR/nodes/config/n3/data --pidfilepath $WORK_DIR/nodes/config/n3/db.pid --logpath $WORK_DIR/nodes/config/n3/db.log --config $CONFFILE
待成功啟動后,輸出日志如下:
about to fork child process, waiting until server is ready for connections.
forked process: 4976
child process started successfully, parent exiting
此時通過ps 命令也可以看到3個啟動的進程實例。
連接其中一個Config進程,執行副本集初始化
./bin/mongo --port 26001 --host 127.0.0.1
> MongoDB server version: 3.4.7
> cfg={
_id:"configReplSet",
configsvr: true,
members:[
{_id:0, host:'127.0.0.1:26001'},
{_id:1, host:'127.0.0.1:26002'},
{_id:2, host:'127.0.0.1:26003'}
]};
rs.initiate(cfg);
其中configsvr:true指明這是一個用於分片集群的Config副本集。
關於副本集配置可參考這里
2. 創建分片
按以下腳本啟動Shard1的3個實例
WORK_DIR=/opt/local/mongo-cluster
KEYFILE=$WORK_DIR/keyfile/mongo.key
CONFFILE=$WORK_DIR/conf/mongo_node.conf
MONGOD=$WORK_DIR/bin/mongod
echo "start shard1 replicaset"
$MONGOD --port 27001 --shardsvr --replSet shard1 --keyFile $KEYFILE --dbpath $WORK_DIR/nodes/shard1/n1/data --pidfilepath $WORK_DIR/nodes/shard1/n1/db.pid --logpath $WORK_DIR/nodes/shard1/n1/db.log --config $CONFFILE
$MONGOD --port 27002 --shardsvr --replSet shard1 --keyFile $KEYFILE --dbpath $WORK_DIR/nodes/shard1/n2/data --pidfilepath $WORK_DIR/nodes/shard1/n2/db.pid --logpath $WORK_DIR/nodes/shard1/n2/db.log --config $CONFFILE
$MONGOD --port 27003 --shardsvr --replSet shard1 --keyFile $KEYFILE --dbpath $WORK_DIR/nodes/shard1/n3/data --pidfilepath $WORK_DIR/nodes/shard1/n3/db.pid --logpath $WORK_DIR/nodes/shard1/n3/db.log --config $CONFFILE
待成功啟動后,輸出日志如下:
about to fork child process, waiting until server is ready for connections.
forked process: 5976
child process started successfully, parent exiting
此時通過ps 命令也可以看到3個啟動的Shard進程實例。
連接其中一個Shard進程,執行副本集初始化
./bin/mongo --port 27001 --host 127.0.0.1
> MongoDB server version: 3.4.7
> cfg={
_id:"shard1",
members:[
{_id:0, host:'127.0.0.1:27001'},
{_id:1, host:'127.0.0.1:27002'},
{_id:2, host:'127.0.0.1:27003'}
]};
rs.initiate(cfg);
參考以上步驟,啟動Shard2的3個實例進程,並初始化副本集。
3. 啟動mongos路由
執行以下腳本啟動3個mongos進程
WORK_DIR=/opt/local/mongo-cluster
KEYFILE=$WORK_DIR/keyfile/mongo.key
CONFFILE=$WORK_DIR/conf/mongos.conf
MONGOS=$WORK_DIR/bin/mongos
echo "start mongos instances"
$MONGOS --port=25001 --configdb configReplSet/127.0.0.1:26001,127.0.0.1:26002,127.0.0.1:26003 --keyFile $KEYFILE --pidfilepath $WORK_DIR/nodes/mongos/n1/db.pid --logpath $WORK_DIR/nodes/mongos/n1/db.log --config $CONFFILE
$MONGOS --port 25002 --configdb configReplSet/127.0.0.1:26001,127.0.0.1:26002,127.0.0.1:26003 --keyFile $KEYFILE --pidfilepath $WORK_DIR/nodes/mongos/n2/db.pid --logpath $WORK_DIR/nodes/mongos/n2/db.log --config $CONFFILE
$MONGOS --port 25003 --configdb configReplSet/127.0.0.1:26001,127.0.0.1:26002,127.0.0.1:26003 --keyFile $KEYFILE --pidfilepath $WORK_DIR/nodes/mongos/n3/db.pid --logpath $WORK_DIR/nodes/mongos/n3/db.log --config $CONFFILE
待成功啟動后,通過ps命令看到mongos進程:
dbuser 7903 1 0 17:49 ? 00:00:00 /opt/local/mongo-cluster/bin/mongos --port=25001 --configdb configReplSet/127.0.0.1:26001,127.0.0.1:26002,127.0.0.1:26003 --keyFile /opt/local/mongo-cluster/keyfile/mongo.key --pidfilepath /opt/local/mongo-cluster/nodes/mongos/n1/db.pid --logpath /opt/local/mongo-cluster/nodes/mongos/n1/db.log --config /opt/local/mongo-cluster/conf/mongos.conf
dbuser 7928 1 0 17:49 ? 00:00:00 /opt/local/mongo-cluster/bin/mongos --port 25002 --configdb configReplSet/127.0.0.1:26001,127.0.0.1:26002,127.0.0.1:26003 --keyFile /opt/local/mongo-cluster/keyfile/mongo.key --pidfilepath /opt/local/mongo-cluster/nodes/mongos/n2/db.pid --logpath /opt/local/mongo-cluster/nodes/mongos/n2/db.log --config /opt/local/mongo-cluster/conf/mongos.conf
dbuser 7954 1 0 17:49 ? 00:00:00 /opt/local/mongo-cluster/bin/mongos --port 25003 --configdb configReplSet/127.0.0.1:26001,127.0.0.1:26002,127.0.0.1:26003 --keyFile /opt/local/mongo-cluster/keyfile/mongo.key --pidfilepath /opt/local/mongo-cluster/nodes/mongos/n3/db.pid --logpath /opt/local/mongo-cluster/nodes/mongos/n3/db.log --config /opt/local/mongo-cluster/conf/mongos.conf
接入其中一個mongos實例,執行添加分片操作:
./bin/mongo --port 25001 --host 127.0.0.1
mongos> MongoDB server version: 3.4.7
mongos> sh.addShard("shard1/127.0.0.1:27001")
{ "shardAdded" : "shard1", "ok" : 1 }
mongos> sh.addShard("shard2/127.0.0.1:27004")
{ "shardAdded" : "shard2", "ok" : 1 }
至此,分布式集群架構啟動完畢,但進一步操作需要先添加用戶。
4. 初始化用戶
接入其中一個mongos實例,添加管理員用戶
use admin
db.createUser({
user:'admin',pwd:'Admin@01',
roles:[
{role:'clusterAdmin',db:'admin'},
{role:'userAdminAnyDatabase',db:'admin'},
{role:'dbAdminAnyDatabase',db:'admin'},
{role:'readWriteAnyDatabase',db:'admin'}
]})
當前admin用戶具有集群管理權限、所有數據庫的操作權限。
需要注意的是,在第一次創建用戶之后,localexception不再有效,接下來的所有操作要求先通過鑒權。
use admin
db.auth('admin','Admin@01')
檢查集群狀態
mongos> sh.status()
--- Sharding Status ---
sharding version: {
"_id" : 1,
"minCompatibleVersion" : 5,
"currentVersion" : 6,
"clusterId" : ObjectId("5aa39c3e915210dc501a1dc8")
}
shards:
{ "_id" : "shard1", "host" : "shard1/127.0.0.1:27001,127.0.0.1:27002,127.0.0.1:27003", "state" : 1 }
{ "_id" : "shard2", "host" : "shard2/127.0.0.1:27004,127.0.0.1:27005,127.0.0.1:27006", "state" : 1 }
active mongoses:
"3.4.7" : 3
autosplit:
Currently enabled: yes
集群用戶
分片集群中的訪問都會通過mongos入口,而鑒權數據是存儲在config副本集中的,即config實例中system.users數據庫存儲了集群用戶及角色權限配置。mongos與shard實例則通過內部鑒權(keyfile機制)完成,因此shard實例上可以通過添加本地用戶以方便操作管理。在一個副本集上,只需要在Primary節點上添加用戶及權限,相關數據會自動同步到Secondary節點。
關於集群鑒權
在本案例中,我們為兩個分片副本集都添加了本地admin用戶。
通過mongostat工具可以顯示集群所有角色:
host insert query update delete getmore command dirty used flushes mapped vsize res faults qrw arw net_in net_out conn set repl time
127.0.0.1:27001 *0 *0 *0 *0 0 6|0 0.1% 0.1% 0 1.49G 44.0M n/a 0|0 0|0 429b 56.1k 25 shard1 PRI Mar 10 19:05:13.928
127.0.0.1:27002 *0 *0 *0 *0 0 7|0 0.1% 0.1% 0 1.43G 43.0M n/a 0|0 0|0 605b 55.9k 15 shard1 SEC Mar 10 19:05:13.942
127.0.0.1:27003 *0 *0 *0 *0 0 7|0 0.1% 0.1% 0 1.43G 43.0M n/a 0|0 0|0 605b 55.9k 15 shard1 SEC Mar 10 19:05:13.946
127.0.0.1:27004 *0 *0 *0 *0 0 6|0 0.1% 0.1% 0 1.48G 43.0M n/a 0|0 0|0 546b 55.8k 18 shard2 PRI Mar 10 19:05:13.939
127.0.0.1:27005 *0 *0 *0 *0 0 6|0 0.1% 0.1% 0 1.43G 42.0M n/a 0|0 0|0 540b 54.9k 15 shard2 SEC Mar 10 19:05:13.944
127.0.0.1:27006 *0 *0 *0 *0 0 6|0 0.1% 0.1% 0 1.46G 44.0M n/a 0|0 0|0 540b 54.9k 17 shard2 SEC Mar 10 19:05:13.936
五、數據操作
在案例中,創建appuser用戶、為數據庫實例appdb啟動分片。
use appdb
db.createUser({user:'appuser',pwd:'AppUser@01',roles:[{role:'dbOwner',db:'appdb'}]})
sh.enableSharding("appdb")
創建集合book,為其執行分片初始化。
use appdb
db.createCollection("book")
db.device.ensureIndex({createTime:1})
sh.shardCollection("appdb.book", {bookId:"hashed"}, false, { numInitialChunks: 4} )
繼續往device集合寫入1000W條記錄,觀察chunks的分布情況
use appdb
var cnt = 0;
for(var i=0; i<1000; i++){
var dl = [];
for(var j=0; j<100; j++){
dl.push({
"bookId" : "BBK-" + i + "-" + j,
"type" : "Revision",
"version" : "IricSoneVB0001",
"title" : "Jackson's Life",
"subCount" : 10,
"location" : "China CN Shenzhen Futian District",
"author" : {
"name" : 50,
"email" : "RichardFoo@yahoo.com",
"gender" : "female"
},
"createTime" : new Date()
});
}
cnt += dl.length;
db.book.insertMany(dl);
print("insert ", cnt);
}
執行db.book.getShardDistribution(),輸出如下:
Shard shard1 at shard1/127.0.0.1:27001,127.0.0.1:27002,127.0.0.1:27003
data : 13.41MiB docs : 49905 chunks : 2
estimated data per chunk : 6.7MiB
estimated docs per chunk : 24952
Shard shard2 at shard2/127.0.0.1:27004,127.0.0.1:27005,127.0.0.1:27006
data : 13.46MiB docs : 50095 chunks : 2
estimated data per chunk : 6.73MiB
estimated docs per chunk : 25047
Totals
data : 26.87MiB docs : 100000 chunks : 4
Shard shard1 contains 49.9% data, 49.9% docs in cluster, avg obj size on shard : 281B
Shard shard2 contains 50.09% data, 50.09% docs in cluster, avg obj size on shard : 281B
總結
- Mongodb集群架構由Mongos、Config副本集和多個分片組成;
安裝過程中先初始化Config副本集、分片副本集,最后通過Mongos添加分片 - Config副本集存儲了集群訪問的用戶及角色權限,為了方便管理,可以給分片副本集添加本地用戶
- Mongodb提供了LocalException機制,首次安裝數據庫時可以在本機直接添加用戶