概述
MongoDB 集群分片是一种水平扩展数据库的方法,通过将数据分布在多个物理服务器上,提高系统的性能和可扩展性。分片的核心思想是将数据分成多个部分(称为“分片”),每个分片存储在不同的服务器上,从而分散负载,提高查询和写入性能。
使用场景
优缺点
优点
缺点
节点作用
下载地址
MongoDB Community Downloads | MongoDB
配置hosts解下
vim /etc/hosts
10.10.10.21 mon1
10.10.10.22 mon2
10.10.10.23 mon3
集群规划
10.10.10.21 mon1:mongos(30000)\config(27017-主)\shard1(40001-主)\shard2(40002-从)\shard3(40003-从)
10.10.10.22 mon2:mongos(30000)\config(27017-从)\shard1(40001-从)\shard2(40002-主)\shard3(40003-从)
10.10.10.23 mon3:mongos(30000)\config(27017-从)\shard1(40001-从)\shard2(40002-从)\shard3(40003-主)
3台机,每台机5个组件,分别mongos 1 个,config server 1 个,shard server 3 个
部署
解压(三台机器)
mongosh:
wget https://downloads.mongodb.com/compass/mongosh-2.3.1-linux-x64.tgz
tar xvf mongosh-2.3.1-linux-x64.tgz
mongodb:
tar xvf mongodb-linux-x86_64-rhel70-7.0.14.tgz
mv mongodb-linux-x86_64-rhel70-7.0.14 mongodb
创建相关目录(三台机器)
[root@easyliao012 monogocluster]# mkdir -p /monogocluster/shard{1,2,3}/{config,log,data}
[root@easyliao012 monogocluster]#mkdir -p /monogocluster/mongos/{config,log,data}
[root@easyliao012 monogocluster]# mkdir -p /monogocluster/config/{config,log,data}
内存配置
shard 和 config 服务器的 WiredTiger 缓存大小的分配建议:
1. Shard 服务器的缓存大小分配:
对于每个 Shard 服务器,可以根据数据量和预计的工作负载来调整缓存大小。一般来说,将缓存大小设置为机器内存的 50%-75% 是比较常见的做法。
例如,如果你的Shard服务器有16GB的内存,可以将缓存大小设置为8GB-12GB,即 wiredTiger.engineConfig.cacheSizeGB:8
或者wiredTiger.engineConfig.cacheSizeGB:12。
这样可以让MongoDB利用一部分内存来缓存数据和索引,提高读取操作的性能
2. Config 服务器的缓存大小分配:
Config 服务器主要用于存储集群的元数据信息,相对来说对内存的需求较小。通常可以将缓存大小设置为机器内存的 25%-50%。
例如,如果你的 Config 服务器有 8GB 的内存,可以将缓存大小设置为 2GB - 4GB,即 wiredTiger.engineConfig.cacheSizeGB: 2
或者 wiredTiger.engineConfig.cacheSizeGB: 4。
需要注意的是,缓存大小的分配应该综合考虑系统内存大小、数据量、查询模式等因素,以达到最佳性能和资源利用的平衡点。
配置集群分片配置文件
配置文件config(三台机器)
vim /monogocluster/config/config/mongo-conf
# 日志设置
systemLog:
destination: file # 日志写入文件
path: /monogocluster/config/log/mongodb.log # 日志文件路径
logAppend: true # 追加日志
logRotate: rename # 日志轮转方式,支持 rename 或 reopen
# 网络设置
net:
port: 27017 # MongoDB 默认端口
bindIp: 0.0.0.0 # 允许从所有 IP 访问,生产环境建议限制
# 数据目录
storage:
dbPath: /monogocluster/config/data # 数据文件存放路径
wiredTiger:
engineConfig:
cacheSizeGB: 3 # 根据情况配置内存
# 进程设置
processManagement:
fork: true # 以后台进程方式运行
pidFilePath: /monogocluster/config/data/mongod.pid # PID 文件路径
#复制集名称
replication:
replSetName: "mgconfig"
#作为配置服务
sharding:
clusterRole: configsvr
配置文件mongos(三台机器)
vim /monogocluster/mongos/config/mongo-conf
# 日志设置
systemLog:
destination: file # 日志写入文件
path: /monogocluster/mongos/log/mongodb.log # 日志文件路径
logAppend: true # 追加日志
logRotate: rename # 日志轮转方式,支持 rename 或 reopen
# 网络设置
net:
port: 30000 # MongoDB 默认端口
bindIp: 0.0.0.0 # 允许从所有 IP 访问,生产环境建议限制
# 进程设置
processManagement:
fork: true # 以后台进程方式运行
pidFilePath: /monogocluster/mongos/data/mongod.pid # PID 文件路径
#网络延迟阈值
replication:
localPingThresholdMs: 15
#关联配置服务
sharding:
configDB: mgconfig/mon1:27017,mon2:27017,mon3:27017
配置文件mongoshard1(三台机器)
vim /monogocluster/shard1/config/mongo-conf
# 日志设置
systemLog:
destination: file # 日志写入文件
path: /monogocluster/shard1/log/mongodb.log # 日志文件路径
logAppend: true # 追加日志
logRotate: rename # 日志轮转方式,支持 rename 或 reopen
# 网络设置
net:
port: 40001 # MongoDB 默认端口
bindIp: 0.0.0.0 # 允许从所有 IP 访问,生产环境建议限制
# 数据目录
storage:
dbPath: /monogocluster/shard1/data # 数据文件存放路径
wiredTiger:
engineConfig:
cacheSizeGB: 7 # 根据情况配置内存
# 进程设置
processManagement:
fork: true # 以后台进程方式运行
pidFilePath: /monogocluster/shard1/data/mongod.pid # PID 文件路径
#复制集名称
replication:
replSetName: "shard1"
#慢查询
operationProfiling:
slowOpThresholdMs : 100
mode: "slowOp"
#作为分片服务
sharding:
clusterRole: shardsvr
配置文件mongoshard2(三台机器)
vim /monogocluster/shard2/config/mongo-conf
# 日志设置
systemLog:
destination: file # 日志写入文件
path: /monogocluster/shard2/log/mongodb.log # 日志文件路径
logAppend: true # 追加日志
logRotate: rename # 日志轮转方式,支持 rename 或 reopen
# 网络设置
net:
port: 40002 # MongoDB 默认端口
bindIp: 0.0.0.0 # 允许从所有 IP 访问,生产环境建议限制
# 数据目录
storage:
dbPath: /monogocluster/shard2/data # 数据文件存放路径
wiredTiger:
engineConfig:
cacheSizeGB: 7 # 根据情况配置内存
# 进程设置
processManagement:
fork: true # 以后台进程方式运行
pidFilePath: /monogocluster/shard2/data/mongod.pid # PID 文件路径
#复制集名称
replication:
replSetName: "shard2"
#慢查询
operationProfiling:
slowOpThresholdMs : 100
mode: "slowOp"
#作为分片服务
sharding:
clusterRole: shardsvr
配置文件mongoshard3(三台机器)
vim /monogocluster/shard3/config/mongo-conf
# 日志设置
systemLog:
destination: file # 日志写入文件
path: /monogocluster/shard3/log/mongodb.log # 日志文件路径
logAppend: true # 追加日志
logRotate: rename # 日志轮转方式,支持 rename 或 reopen
# 网络设置
net:
port: 40003 # MongoDB 默认端口
bindIp: 0.0.0.0 # 允许从所有 IP 访问,生产环境建议限制
# 数据目录
storage:
dbPath: /monogocluster/shard3/data # 数据文件存放路径
wiredTiger:
engineConfig:
cacheSizeGB: 7 # 根据情况配置内存
# 进程设置
processManagement:
fork: true # 以后台进程方式运行
pidFilePath: /monogocluster/shard3/data/mongod.pid # PID 文件路径
#复制集名称
replication:
replSetName: "shard3"
#慢查询
operationProfiling:
slowOpThresholdMs : 100
mode: "slowOp"
#作为分片服务
sharding:
clusterRole: shardsvr
启动config服务并配置复制集(3台机器执行相同操作)
/opt/mongodb/bin/mongod --config /monogocluster/config/config/mongo-conf
连接一个config实例
mongosh mongodb://easyliao012:27017
初始化复制集
这个 mgconfig 名字一定要和config 配置文件中 replSet 的名字一致
config={_id:"mgconfig",members:[
{_id:0,host:"mon1:27017"},
{_id:1,host:"mon2:27017"},
{_id:2,host:"mon3:27017"},
]};
rs.initiate(config)
rs.status()
启动shard分片并配置副本集
---shard1
##启动
/opt/mongodb/bin/mongod --config /monogocluster/shard1/config/mongo-conf
##配置副本集
权重越高priority:3会被指定为主节点
连接任意一个shard1实例
[root@mysql1 bin]# mongosh mongodb://mon1:40001
创建复制集
use admin
config={_id:"shard1",members:[
{_id:0,host:"mon1:40001",priority:3},
{_id:1,host:"mon2:40001",priority:1},
{_id:2,host:"mon3:40001",priority:1},
]}
rs.initiate(config)
rs.status()
--shard2
##启动
/opt/mongodb/bin/mongod --config /monogocluster/shard2/config/mongo-conf
##配置副本集
连接任意一个shard2实例
[root@mysql1 bin]# mongosh mongodb://mon2:40002
创建复制集
use admin
config={_id:"shard2",members:[
{_id:0,host:"mon1:40002",priority:1},
{_id:1,host:"mon2:40002",priority:3},
{_id:2,host:"mon3:40002",priority:1},
]}
rs.initiate(config)
rs.status()
---shard3
##启动
/opt/mongodb/bin/mongod --config /monogocluster/shard3/config/mongo-conf
##配置副本集
连接任意一个shard3实例
[root@mysql1 bin]# mongosh mongodb://mon3:40003
创建复制集
use admin
config={_id:"shard3",members:[
{_id:0,host:"mon1:40003",priority:1},
{_id:1,host:"mon2:40003",priority:1},
{_id:2,host:"mon3:40003",priority:3},
]};
rs.initiate(config)
rs.status()
启动mongos并添加分片
##启动
/opt/mongodb/bin/mongos --config /monogocluster/mongos/config/mongo-conf
##登陆路由节点
mongosh mongodb://mon1:30000
use admin
##添加分片
sh.addShard("shard1/mon1:40001,mon2:40001,mon3:40001")
sh.addShard("shard2/mon1:40002,mon2:40002,mon3:40002")
sh.addShard("shard3/mon1:40003,mon2:40003,mon3:40003")
##查看状态
[direct: mongos] admin> sh.status();
shardingVersion
{ _id: 1, clusterId: ObjectId("66f50c31e8f91dc6de9b9770") }
---
shards
[
{
_id: 'shard1',
host: 'shard1/mon1:40001,mon2:40001,mon3:40001',
state: 1,
topologyTime: Timestamp({ t: 1727338491, i: 3 })
},
{
_id: 'shard2',
host: 'shard2/mon1:40002,mon2:40002,mon3:40002',
state: 1,
topologyTime: Timestamp({ t: 1727338512, i: 1 })
},
{
_id: 'shard3',
host: 'shard3/mon1:40003,mon2:40003,mon3:40003',
state: 1,
topologyTime: Timestamp({ t: 1727338518, i: 3 })
}
]
---
active mongoses
[ { '7.0.14': 3 } ]
---
autosplit
{ 'Currently enabled': 'yes' }
---
balancer
{ 'Currently enabled': 'yes', 'Currently running': 'no' }
---
databases
[
{
database: { _id: 'config', primary: 'config', partitioned: true },
collections: {}
}
]
创建账户
##在mongos创建一个管理员账户用于数据库操作,
mongosh mongodb://mon1:30000
mongos>use admin
mongos>db.createUser({user:"root",pwd:"sdhjfREWFWEF23e",roles:["root"]})
mongos>db.auth("root","sdhjfREWFWEF23e")
##在shard1、shard2、shard3分别创建副本集管理员账户,每个分片都要创建主节点上
mongosh mongodb://mon1:40001
mongosh mongodb://mon2:40002
mongosh mongodb://mon3:40003
mongos>use admin
mongos>db.createUser({user:"root",pwd:"sdhjfREWFWEF23e",roles:["root"]})
mongos>db.auth("root","sdhjfREWFWEF23e")
安全认证
##创建秘钥文件
openssl rand -base64 753 >/monogocluster/config/mongo-keyfile
#将主节点生成的mongo-keyfile文件拷贝到其他服务器目录,注意权限
chmod 600 /monogocluster/config/mongo-keyfile
##拷贝秘钥
root@mysql1 bin]# scp keyFile.key mongodb@mon2:/monogocluster/config/
root@mysql1 bin]# scp keyFile.key mongodb@mon3:/monogocluster/config/
修改config server,shard1,shard2,shard3配置文件,增加如下参数:
security:
authorization: "enabled"
keyFile: /monogocluster/config/mongo-keyfile
修改mongos 配置文件,增加如下参数:
security:
keyFile: /monogocluster/config/mongo-keyfile
关闭服务
关闭集群
第一步:关闭所有mongos路由实例
第二步:关闭所有分片
第三步:关闭所有的配置服务器
##关闭mongos
mongosh mongodb://127.0.0.1:30000
use admin
db.auth('root','sdhjfREWFWEF23e')
db.shutdownServer()
##关闭分片
/opt/mongodb/bin/mongod --config /monogocluster/shard3/config/mongo-conf --shutdown
/opt/mongodb/bin/mongod --config /monogocluster/shard2/config/mongo-conf --shutdown
/opt/mongodb/bin/mongod --config /monogocluster/shard1/config/mongo-conf --shutdown
##关闭configservers
/opt/mongodb/bin/mongod --config /monogocluster/config/config/mongo-conf --shutdown
启动服务
启动集群
第一步:启动配置服务器
第二步:启动所有分片
第三步:启动mongos路由实例
##启动配置服务
/opt/mongodb/bin/mongod --config /monogocluster/config/config/mongo-conf
##启动所有分片
/opt/mongodb/bin/mongod --config /monogocluster/shard1/config/mongo-conf
/opt/mongodb/bin/mongod --config /monogocluster/shard2/config/mongo-conf
/opt/mongodb/bin/mongod --config /monogocluster/shard3/config/mongo-conf
## 启动mongos路由实例
/opt/mongodb/bin/mongos --config /monogocluster/mongos/config/mongo-conf
验证数据库
--- 测试服务器分片功能
mongosh mongodb://127.0.0.1:30000
[direct: mongos] test> use admin
[direct: mongos] admin> db.auth('root','sdhjfREWFWEF23e')
--- 启用数据库分片
sh.enableSharding("db2")
--- 启用表分片
sh.shardCollection("db2.user",{"id":1})
sh.shardCollection("db2.user1",{"id":"hashed"})
--- 模拟写入数据
在db2库的user表中循环写入数据
use db2
for(i=1;i<=600;i++){db.tyuser3.insert({"id":i,"name":"ty"+i})}
---查看集群情况
[direct: mongos] db2> sh.status()
shardingVersion
{ _id: 1, clusterId: ObjectId("66f50c31e8f91dc6de9b9770") }
shards
[{
_id: 'shard1',
host: 'shard1/mon1:40001,mon2:40001,mon3:40001',
state: 1,
topologyTime: Timestamp({ t: 1727338491, i: 3 })
},{
_id: 'shard2',
host: 'shard2/mon1:40002,mon2:40002,mon3:40002',
state: 1,
topologyTime: Timestamp({ t: 1727338512, i: 1 })
},{
_id: 'shard3',
host: 'shard3/mon1:40003,mon2:40003,mon3:40003',
state: 1,
topologyTime: Timestamp({ t: 1727338518, i: 3 })
}]
active mongoses
[ { '7.0.14': 3 } ]
---查看集合分片情况
var dbName = "db2";
db.getSiblingDB(dbName).getCollectionNames().forEach(function(collName) {
print("————————————————————————");
print("Collection: " + collName);
db.getSiblingDB(dbName).getCollection(collName).getShardDistribution();
});
输出结果
————————————————————————
Collection: user1
Shard shard1 at shard1/mon1:40001,mon2:40001,mon3:40001
data : 9KiB docs : 214 chunks : 0
estimated data per chunk : InfinityGiB
estimated docs per chunk : Infinity
Shard shard3 at shard3/mon1:40003,mon2:40003,mon3:40003
data : 7KiB docs : 175 chunks : 0
estimated data per chunk : InfinityGiB
estimated docs per chunk : Infinity
Shard shard2 at shard2/mon1:40002,mon2:40002,mon3:40002
data : 9KiB docs : 211 chunks : 0
estimated data per chunk : InfinityGiB
estimated docs per chunk : Infinity
Totals
data : 26KiB docs : 600 chunks : 0
Shard shard1 contains 35.64% data, 35.66% docs in cluster, avg obj size on shard : 45B
Shard shard3 contains 29.19% data, 29.16% docs in cluster, avg obj size on shard : 45B
Shard shard2 contains 35.16% data, 35.16% docs in cluster, avg obj size on shard : 45B
————————————————————————
Collection: user
Shard shard3 at shard3/mon1:40003,mon2:40003,mon3:40003
data : 26KiB docs : 600 chunks : 0
estimated data per chunk : InfinityGiB
estimated docs per chunk : Infinity
Totals
data : 26KiB docs : 600 chunks : 0
Shard shard3 contains 100% data, 100% docs in cluster, avg obj size on shard : 45B
总结
MongoDB 集群分片是一种强大的水平扩展解决方案,适用于大规模数据存储和高并发访问场景。通过将数据分布在多个物理服务器上,分片可以显著提高系统的性能和可扩展性。然而,分片架构的复杂性和管理成本也需要仔细考虑。在选择分片键和配置集群时,应根据业务需求和数据特性进行优化,以充分发挥分片的优势。