当MongoDB的单机性能达到瓶颈后,我们需要将集合分散到多个机器上进行分片(sharding),以便解决数据量增长时的性能问题。而MongoDB的分片功能强大,其架构的分散性和弹性也非常好。所以分片是MongoDB的一个核心功能。
以下是MongoDB分片测试的完整攻略:
运行环境
- 主机1:192.168.100.1
- 主机2:192.168.100.2
两台主机的硬件配置都是:16核CPU,64GB内存,硬盘存储使用了RAID 0。操作系统为CentOS 7,安装有MongoDB 4.2版本。
安装配置MongoDB集群
在两台主机上都需要安装MongoDB 4.2,并进行安装和配置。因为在分片的架构中,我们至少需要有3个节点:mongos,config,和shard。其中,mongos节点是控制器,用来将数据分散到shard节点;config节点是MongoDB的元数据库,用于存储集群元信息和配置;shard节点则是数据存储容器。
该部分详细步骤请参考MongoDB4.2安装配置,这里不再赘述。
配置目标文件
接下来需要修改目标文件的配置。以每个节点的配置为例:
mongos节点
mongos节点的目标文件通常在/etc/mongos.conf路径下,需要添加以下内容:
net:
port: 27017
systemLog:
destination: file
path: /var/log/mongodb/mongos.log
logAppend: true
processManagement:
fork: true
setParameter:
enableLocalhostAuthBypass: false
sharding:
configDB: config01/config02/config03
其中,mongos的默认端口为27017,systemLog选项用于配置日志,fork选项则表示在后台运行mongos。setParameter选项使mongos在本地验证HOST代替AUTH。最后,sharding选项配置configDB参数,标识了元数据库的主机名或IP地址以及端口号。
config节点
config节点的目标文件通常在/etc/mongod.conf路径下,需要添加以下内容:
net:
port: 27017
systemLog:
destination: file
path: /var/log/mongodb/config01.log
logAppend: true
processManagement:
fork: true
sharding:
clusterRole: "configsvr"
replication:
replSetName: "config01"
其中,net选项配置端口信息,systemLog选项用于配置日志,fork选项则表示在后台运行mongod。sharding选项标志该节点的clusterRole为configsvr,并指定了复制集名称。replication选项同样指定了该节点的复制集名称。
shard节点
shard节点的目标文件通常在/etc/mongod.conf路径下,需要添加以下内容:
net:
port: 27017
storage:
dbPath: /data/mongodb/shard1
systemLog:
destination: file
path: /var/log/mongodb/shard1.log
logAppend: true
processManagement:
fork: true
sharding:
clusterRole: "shardsvr"
replication:
replSetName: "shard1"
其中,net选项配置端口信息,storage选项用于指定数据存储路径,systemLog选项用于配置日志,fork选项表示在后台运行,sharding选项标志该节点的clusterRole为shardsvr,并指定了该节点所在复制集的名称。replication选项同样指定了该节点的复制集名称。
启动MongoDB集群
所有节点都启动后打开命令行输入mongo
启动mongo shell。进入mongo shell后,使用sh.addShard()
方法将shard节点添加到mongos上(示例:向mongos添加位于主机192.168.100.2的shard节点):
sh.addShard("192.168.100.2:27017")
使用sh.enableSharding()
方法开启分片功能:
sh.enableSharding("test")
其中,"test"是你将要用来分片的数据库名称。
第二个步骤完成后,在将要分片的集合中进行数据插入测试。首先使用mongo shell命令:
use test
db.createCollection("users")
然后向该集合插入数据:
for(var i=0;i<10000000;i++){
var age=Math.floor(Math.random()*50)+18;
db.users.insert({"name":"user"+i,"age":age})
}
以上步骤完成后,使用sh.shardCollection()
方法对集合进行分片:
sh.shardCollection("test.users",{age:1})
其中,age:1表示对age字段进行升序分片。
最后,我们可以使用db.users.getShardDistribution()
方法来查看分片状态。如果分片状态正常,MongoDB集群分片测试就完成了。
分片测试的两条示例
- 示例一:单文档查询测试
使用以下mongo shell命令进行测试:
db.users.findOne().pretty()
预期结果为:
{
"_id" : ObjectId("5f52fbe04ff8de7e9c3e1d6e"),
"name" : "user0",
"age" : 58
}
可以看到,该命令返回了一个单一文档,用来测试单机性能和查询速度。
- 示例二:基于条件的数据查询测试
使用以下mongo shell命令进行测试:
db.users.find({age:{$gt:50}}).sort({"name":1}).limit(10).pretty()
预期结果为:
{
"_id" : ObjectId("5f52fbe84ff8de7e9c3e3330"),
"name" : "user102130",
"age" : 51
}
{
"_id" : ObjectId("5f52fbe74ff8de7e9c3e2d9b"),
"name" : "user101915",
"age" : 51
}
{
"_id" : ObjectId("5f52fbe54ff8de7e9c3e27ad"),
"name" : "user101583",
"age" : 51
}
{
"_id" : ObjectId("5f52fbe44ff8de7e9c3e21d1"),
"name" : "user101289",
"age" : 51
}
{
"_id" : ObjectId("5f52fbe04ff8de7e9c3e1d6e"),
"name" : "user0",
"age" : 58
}
{
"_id" : ObjectId("5f52fbe74ff8de7e9c3e2cdf"),
"name" : "user101662",
"age" : 52
}
{
"_id" : ObjectId("5f52fbe84ff8de7e9c3e3259"),
"name" : "user102018",
"age" : 52
}
{
"_id" : ObjectId("5f52fbe74ff8de7e9c3e2ad1"),
"name" : "user101790",
"age" : 53
}
{
"_id" : ObjectId("5f52fbe54ff8de7e9c3e2692"),
"name" : "user101539",
"age" : 53
}
{
"_id" : ObjectId("5f52fbe84ff8de7e9c3e32b5"),
"name" : "user102049",
"age" : 54
}
可以看到,该命令返回了一个符合条件的数据子集,用于测试分片性能和复杂度。