mongodb 学习之——Linux 下MongoDB 分片集群 Shard Cluster搭建
一、准备
linux 下指定配置文件安装mongodb
二、分片集群原理部分
什么是分片
分片(sharding)是MongoDB用来将大型集合水平分割到不同服务器(或者复制集)上所采用的方法。不需要功能强大的大型计算机就可以存储更多的数据,处理更大的负载。
为什么要分片
1.存储容量需求超出单机磁盘容量。
2.活跃的数据集超出单机内存容量,导致很多请求都要从磁盘读取数据,影响性能。
3.IOPS超出单个MongoDB节点的服务能力,随着数据的增长,单机实例的瓶颈会越来越明显。
4.副本集具有节点数量限制。
垂直扩展:增加更多的CPU和存储资源来扩展容量。
水平扩展:将数据集分布在多个服务器上。水平扩展即分片。
分片的工作原理
分片集群由以下3个服务组成:
Shards Server: 每个shard由一个或多个mongod进程组成,用于存储数据。
Router Server: 数据库集群的请求入口,所有请求都通过Router(mongos)进行协调,不需要在应用程,序添加一个路由选择器,Router(mongos)就是一个请求分发中心它负责把应用程序的请求转发到对应的Shard服务器上。
Config Server: 配置服务器。存储所有数据库元信息(路由、分片)的配置。
片键(shard key)
为了在数据集合中分配文档,MongoDB使用分片主键分割集合
区块(chunk)
在一个shard server内部,MongoDB还是会把数据分为chunks,每个chunk代表这个shard server内部一部分数据。MongoDB分割分片数据到区块,每一个区块包含基于分片主键的左闭右开的区间范围
分片策略
- 范围分片(Range based sharding)
范围分片适合满足在一定范围内的查找,例如查找X的值在[20,30)之间的数据,mongo 路由根据Config server中存储的元数据,可以直接定位到指定的shard的Chunk中。
缺点: 如果shard key有明显递增(或者递减)趋势,则新插入的文档多会分布到同一个chunk,无法扩展写的能力。
- hash分片(Hash based sharding)
Hash分片是计算一个分片主键的hash值,每一个区块将分配一个范围的hash值。Hash分片与范围分片互补,能将文档随机的分散到各个chunk,充分的扩展写能力,弥补了范围分片的不足,缺点是不能高效的服务范围查询,所有的范围查询要分发到后端所有的Shard才能找出满足条件的文档
- 组合片键 A + B(散列思想 不能是直接hash)
数据库中没有比较合适的片键供选择,或者是打算使用的片键基数太小(即变化少如星期只有7天可变化),可以选另一个字段使用组合片键,甚至可以添加冗余字段来组合。一般是粗粒度+细粒度进行组合。
三、分片集群搭建过程
1.配置 并启动config 节点集群
节点1 config-17017.conf
# 数据库文件位置 dbpath=config/config1 #日志文件位置 logpath=config/logs/config1.log # 以追加方式写入日志 logappend=true # 是否以守护进程方式运行 fork = true bind_ip=0.0.0.0 port = 17017 # 表示是一个配置服务器 configsvr=true #配置服务器副本集名称 replSet=configsvr # 数据库文件位置
节点2 config-17018.conf
# 数据库文件位置 节点3 config-17019.conf 启动配置节点 进入任意节点的mongo shell 并添加 配置节点集群 注意use admin dbpath=config/config2 #日志文件位置 logpath=config/logs/config.log # 以追加方式写入日志 logappend=true # 是否以守护进程方式运行 fork = true bind_ip=0.0.0.0 port = 17018 # 表示是一个配置服务器 configsvr=true #配置服务器副本集名称 replSet=configsvr
节点3 config-17019.conf
# 数据库文件位置 dbpath=config/config3 #日志文件位置 logpath=config/logs/config3.log # 以追加方式写入日志 logappend=true # 是否以守护进程方式运行 fork = true bind_ip=0.0.0.0 port = 17019 # 表示是一个配置服务器 configsvr=true #配置服务器副本集名称 replSet=configsvr
启动配置节点
./bin/mongod -f config/config-17017.conf ./bin/mongod -f config/config-17018.conf ./bin/mongod -f config/config-17019.conf
进入任意节点的mongo shell 并添加 配置节点集群 注意use admin
./bin/mongo --port 17017 use admin var cfg ={"_id":"configsvr", "members":[ {"_id":1,"host":"192.168.211.133:17017"}, {"_id":2,"host":"192.168.211.133:17018"}, {"_id":3,"host":"192.168.211.133:17019"}] }; rs.initiate(cfg)
实操
mkdir shard_cluster mv mongodb-linux-x86_64-amazon-3.6.21.tgz shard_cluster/ cd shard_cluster/ tar -xvf mongodb-linux-x86_64-amazon-3.6.21.tgz rm -rf mongodb-linux-x86_64-amazon-3.6.21.tgz mv mongodb-linux-x86_64-amazon-3.6.21 shard_cluster cd shard_cluster/
[root@VM_0_4_centos shard_cluster]# mkdir config/config1 -p [root@VM_0_4_centos shard_cluster]# mkdir config/config2 -p [root@VM_0_4_centos shard_cluster]# mkdir config/config3 -p [root@VM_0_4_centos shard_cluster]# mkdir config/logs/ -p
新建节点配置文件,并依次修改10717、17018、17019数据位置,和端口
[root@VM_0_4_centos shard_cluster]# vi mongo_17017.conf
[root@VM_0_4_centos shard_cluster]# cp mongo_17017.conf mongo_17018.conf
[root@VM_0_4_centos shard_cluster]# cp mongo_17017.conf mongo_17019.conf
依次启动各节点
查看配置节点信息
configsvr:SECONDARY> rs.status() { "set" : "configsvr", "date" : ISODate("2020-12-24T07:37:22.074Z"), "myState" : 1, "term" : NumberLong(1), "syncingTo" : "", "syncSourceHost" : "", "syncSourceId" : -1, "configsvr" : true, "heartbeatIntervalMillis" : NumberLong(2000), "optimes" : { "lastCommittedOpTime" : { "ts" : Timestamp(1608795438, 1), "t" : NumberLong(1) }, "readConcernMajorityOpTime" : { "ts" : Timestamp(1608795438, 1), "t" : NumberLong(1) }, "appliedOpTime" : { "ts" : Timestamp(1608795438, 1), "t" : NumberLong(1) }, "durableOpTime" : { "ts" : Timestamp(1608795438, 1), "t" : NumberLong(1) } }, "members" : [ { "_id" : 1, "name" : "152.136.193.58:17017", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 455, "optime" : { "ts" : Timestamp(1608795438, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2020-12-24T07:37:18Z"), "syncingTo" : "", "syncSourceHost" : "", "syncSourceId" : -1, "infoMessage" : "could not find member to sync from", "electionTime" : Timestamp(1608795352, 1), "electionDate" : ISODate("2020-12-24T07:35:52Z"), "configVersion" : 1, "self" : true, "lastHeartbeatMessage" : "" }, { "_id" : 2, "name" : "152.136.193.58:17018", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 99, "optime" : { "ts" : Timestamp(1608795438, 1), "t" : NumberLong(1) }, "optimeDurable" : { "ts" : Timestamp(1608795438, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2020-12-24T07:37:18Z"), "optimeDurableDate" : ISODate("2020-12-24T07:37:18Z"), "lastHeartbeat" : ISODate("2020-12-24T07:37:20.977Z"), "lastHeartbeatRecv" : ISODate("2020-12-24T07:37:21.680Z"), "pingMs" : NumberLong(0), "lastHeartbeatMessage" : "", "syncingTo" : "152.136.193.58:17017", "syncSourceHost" : "152.136.193.58:17017", "syncSourceId" : 1, "infoMessage" : "", "configVersion" : 1 }, { "_id" : 3, "name" : "152.136.193.58:17019", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 99, "optime" : { "ts" : Timestamp(1608795438, 1), "t" : NumberLong(1) }, "optimeDurable" : { "ts" : Timestamp(1608795438, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2020-12-24T07:37:18Z"), "optimeDurableDate" : ISODate("2020-12-24T07:37:18Z"), "lastHeartbeat" : ISODate("2020-12-24T07:37:20.978Z"), "lastHeartbeatRecv" : ISODate("2020-12-24T07:37:21.674Z"), "pingMs" : NumberLong(0), "lastHeartbeatMessage" : "", "syncingTo" : "152.136.193.58:17017", "syncSourceHost" : "152.136.193.58:17017", "syncSourceId" : 1, "infoMessage" : "", "configVersion" : 1 } ], "ok" : 1, "operationTime" : Timestamp(1608795438, 1), "$gleStats" : { "lastOpTime" : Timestamp(1608795342, 1), "electionId" : ObjectId("7fffffff0000000000000001") }, "$clusterTime" : { "clusterTime" : Timestamp(1608795438, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } } } configsvr:PRIMARY>
以上配置节点完成
2.配置shard集群
[root@VM_0_4_centos shard1]# mkdir shard1-37017 shard1-37018 shard1-37019
[root@VM_0_4_centos shard1]# mkdir logs
[root@VM_0_4_centos shard1]# vi shard1_37017.conf
[root@VM_0_4_centos shard1]# cp shard1_37017.conf shard1_37018.conf
[root@VM_0_4_centos shard1]# cp shard1_37018.conf shard1_37019.conf
shard1集群搭建37017到37019
dbpath=shard/shard1/shard1-37017 bind_ip=0.0.0.0 port=37017 fork=true logpath=shard/shard1/shard1-37017.log replSet=shard1 shardsvr=true
dbpath=shard/shard1/shard1-37018 bind_ip=0.0.0.0 port=37018 fork=true logpath=shard/shard1/logs/shard1-37018.log replSet=shard1 shardsvr=true
dbpath=shard/shard1/shard1-37019 bind_ip=0.0.0.0 port=37019 fork=true logpath=shard/shard1/logs/shard1-37019.log replSet=shard1 shardsvr=true
启动每个mongod 然后进入其中一个进行集群配置(之前如果搭建过复制集replica_sets 请先停掉)
var cfg ={"_id":"shard1", "protocolVersion" : 1, "members":[ {"_id":1,"host":"152.136.193.58:37017"}, {"_id":2,"host":"152.136.193.58:37018"}, {"_id":3,"host":"152.136.193.58:37019"} ] }; rs.initiate(cfg) rs.status()
shard1搭建完成
shard2集群搭建47017到47019
dbpath=shard/shard2/shard2-47017 bind_ip=0.0.0.0 port=47017 fork=true logpath=shard/shard2/logs/shard2-47017.log replSet=shard2 shardsvr=true dbpath=shard/shard2/shard2-47018 bind_ip=0.0.0.0 port=47018 fork=true logpath=shard/shard2/logs/shard2-47018.log replSet=shard2 shardsvr=true dbpath=shard/shard2/shard2-47019 bind_ip=0.0.0.0 port=47019 fork=true logpath=shard/shard2/logs/shard2-47019.log replSet=shard2 shardsvr=true
var cfg ={"_id":"shard2", "protocolVersion" : 1, "members":[ {"_id":1,"host":"152.136.193.58:47017"}, {"_id":2,"host":"152.136.193.58:47018"}, {"_id":3,"host":"152.136.193.58:47019"} ] }; rs.initiate(cfg) rs.status()
实操过程 ,参照shard1 过程
3.配置和启动 路由节点
route-27017.conf
port=27017 bind_ip=0.0.0.0 fork=true logpath=route/logs/route.log configdb=configsvr/192.168.211.133:17017,192.168.211.133:17018,192.168.211.133:1 7019
启动路由节点使用 mongos (注意不是mongod)
./bin/mongos -f route/route-27017.conf
4. mongos(路由)中添加分片节点
进入路由mongos
mongo --port 27017
sh.status()
sh.addShard("shard1/152.136.193.58:37017,152.136.193.58:37018,152.136.193.58:37019");
sh.addShard("shard2/152.136.193.58:47017,152.136.193.58:47018,152.136.193.58:47019");
sh.status()
5. 开启数据库和集合分片(指定片键)
继续使用mongos完成分片开启和分片大小设置(路由节点)
为数据库开启分片功能 sh.enableSharding("wg_test") 为指定集合开启分片功能.使用 hash 分片 sh.shardCollection("wg_test.t_datas",{"name":"hashed"})
6. 向集合中插入数据测试
通过路由循环向集合中添加数
use wg_test; for(var i=1;i<= 1000;i++){ db.t_datas.insert({"name":"test"+i, salary:(Math.random()*20000).toFixed(2)}); }
7.验证分片效果
分别进入 shard1 和 shard2 中的数据库 进行验证
down...............................................................ao li gei