一、分片集群介绍
(一)、分片的目的
高数据量和吞吐量的数据库应用会对单机的性能造成较大压力,大的查询量会将单机的CPU耗尽,大的数据量对单机的存储压力较大,最终会耗尽系统的内存而将压力转移到磁盘IO上
为了解决这些问题,有两个基本的方法: 垂直扩展和水平扩展。
垂直扩展
增加更多的CPU和存储资源来扩展容量。
水平扩展
将数据集分布在多个服务器上。水平扩展即分片。
(二)、分片设计思想
分片为应对高吞吐量与大数据量提供了方法。使用分片减少了每个分片需要处理的请求数,因此,通过水平扩展,集群可以提高自己的存储容量和吞吐量。举例来说,当插入一条数据时,应用只需要访问存储这条数据的分片.
使用分片减少了每个分片存储的数据。
(三)、分片集群节点介绍
1、路由节点mongos
* 提供集群单一入口
* 转发应用端请求
* 选择合适数据节点进行读写
* 合并多个数据节点的返回
* 无状态
2、配置节点config
* 所有存、取数据的方式
* 所有shard节点的信息,分片功能的一些配置信息
3、数据节点mongod
* 以复制集为单位
* 横向扩展
* 最大1024分片
* 分片之间数据不重复
* 所有分片在一起才可以完整工作
Mongos本身并不持久化数据,Sharded cluster所有的元数据都会存储到Config Server,而用户的数据会议分散存储到各个shard。Mongos启动后,会从配置服务器加载元数据,开始提供服务,将用户的请求正确路由到对应的碎片。
(四)、MongoDB分片集群特点
* 应用全透明,无特殊处理
* 数据自动均衡
* 动态扩容,无须下线
(五)、分片集群数据分布方式
基于范围
基于Hash
基于zone / tag
二、分片集群中数据分布
(一)、Chunk是什么
在一个shard server内部,MongoDB还是会把数据分为chunks,每个chunk代表这个shard server内部一部分数据。chunk的产生,会有以下两个用途:
Splitting
当一个chunk的大小超过配置中的chunk size时,MongoDB的后台进程会把这个chunk切分成更小的chunk,从而避免chunk过大的情况
Balancing
在MongoDB中,balancer是一个后台进程,负责chunk的迁移,从而均衡各个shard server的负载,系统初始1个chunk,chunk size默认值64M,生产库上选择适合业务的chunk size是最好的。ongoDB会自动拆分和迁移chunks
(二)、chunk特点
(1)使用chunk来存储数据
(2)进群搭建完成之后,默认开启一个chunk,大小是64M,
(3)存储需求超过64M,chunk会进行分裂,如果单位时间存储需求很大,设置更大的chunk
(4)chunk会被自动均衡迁移。
(三)、chunksize的选择
小的chunksize:数据均衡是迁移速度快,数据分布更均匀。数据分裂频繁,路由节点消耗更多资源。大的chunksize:数据分裂少。数据块移动集中消耗IO资源。通常100-200M
(四)、chunk分裂及迁移
随着数据的增长,其中的数据大小超过了配置的chunk size,默认是64M,则这个chunk就会分裂成两个。数据的增长会让chunk分裂得越来越多。
这时候,各个shard 上的chunk数量就会不平衡。这时候,mongos中的一个组件balancer 就会执行自动平衡。把chunk从chunk数量最多的shard节点挪动到数量最少的节点。
(五)、chunkSize 对分裂及迁移的影响
MongoDB 默认的 chunkSize 为64MB,如无特殊需求,建议保持默认值;chunkSize 会直接影响到 chunk 分裂、迁移的行为。
chunkSize 越小,chunk 分裂及迁移越多,数据分布越均衡;反之,chunkSize 越大,chunk 分裂及迁移会更少,但可能导致数据分布不均。
chunkSize 太小,容易出现 jumbo chunk(即shardKey 的某个取值出现频率很高,这些文档只能放到一个 chunk 里,无法再分裂)而无法迁移;chunkSize 越大,则可能出现 chunk 内文档数太多(chunk 内文档数不能超过 250000 )而无法迁移。
chunk 自动分裂只会在数据写入时触发,所以如果将 chunkSize 改小,系统需要一定的时间来将 chunk 分裂到指定的大小。
chunk 只会分裂,不会合并,所以即使将 chunkSize 改大,现有的 chunk 数量不会减少,但 chunk 大小会随着写入不断增长,直到达到目标大小
三、分片集群规划
(一)、IP端⼝规划
db01 10.0.0.51
Shard2_Master 28100
Shard1_Slave 28200
Shard3_Arbiter 28300
Config Server 40000
mongos Server 60000
db02 10.0.0.52
Shard2_Master 28100
Shard1_Slave 28200
Shard3_Arbiter 28300
Config Server 40000
mongos Server 60000
db03 10.0.0.53
Shard2_Master 28100
Shard1_Slave 28200
Shard3_Arbiter 28300
Config Server 40000
mongos Server 60000
(二)、⽬录规划
服务⽬录
/opt/master/{conf,log,pid}
/opt/slave/{conf,log,pid}
/opt/arbiter/{conf,log,pid}
/opt/config/{conf,log,pid}
/opt/mongos/{conf,log,pid}
数据⽬录
/data/master
/data/slave
/data/arbiter
/data/config
搭建步骤
1.搭建部署shard副本集
2.搭建部署config副本集
3.搭建mongos
4.添加分⽚成员
5.数据库启动分⽚功能
6.集合设置⽚键
7.写⼊测试数据
8.检查分⽚效果
四、分片集群搭建
1、环境准备
部署单节点mongo
pkill mongo
rm -rf /opt/mongo_2*
rm -rf /data/mongo_2*
rsync -avz /opt/mongodb* 10.0.0.52:/opt/
rsync -avz /opt/mongodb* 10.0.0.53:/opt/
创建相关目录
mkdir -p /opt/master/{conf,log,pid}
mkdir -p /opt/slave/{conf,log,pid}
mkdir -p /opt/arbiter/{conf,log,pid}
mkdir -p /data/master
mkdir -p /data/slave
mkdir -p /data/arbiter
2、副本集配置
①、db01副本集配置
###master配置
cat >/opt/master/conf/mongod.conf<<EOF
systemLog:
destination: file
logAppend: true
path: /opt/master/log/mongodb.log
storage:
journal:
enabled: true
dbPath: /data/master/
directoryPerDB: true
wiredTiger:
engineConfig:
cacheSizeGB: 0.5
directoryForIndexes: true
collectionConfig:
blockCompressor: zlib
indexConfig:
prefixCompression: true
processManagement:
fork: true
pidFilePath: /opt/master/pid/mongodb.pid
timeZoneInfo: /usr/share/zoneinfo
net:
port: 28100
bindIp: 127.0.0.1,$(ifconfig eth0|awk 'NR==2{print $2}')
replication:
oplogSizeMB: 1024
replSetName: shard1
sharding:
clusterRole: shardsvr
EOF
###slave配置
cat >/opt/slave/conf/mongod.conf<<EOF
systemLog:
destination: file
logAppend: true
path: /opt/slave/log/mongodb.log
storage:
journal:
enabled: true
dbPath: /data/slave/
directoryPerDB: true
wiredTiger:
engineConfig:
cacheSizeGB: 0.5
directoryForIndexes: true
collectionConfig:
blockCompressor: zlib
indexConfig:
prefixCompression: true
processManagement:
fork: true
pidFilePath: /opt/slave/pid/mongodb.pid
timeZoneInfo: /usr/share/zoneinfo
net:
port: 28200
bindIp: 127.0.0.1,$(ifconfig eth0|awk 'NR==2{print $2}')
replication:
oplogSizeMB: 1024
replSetName: shard3
sharding:
clusterRole: shardsvr
EOF
###arbiter配置
cat >/opt/arbiter/conf/mongod.conf<<EOF
systemLog:
destination: file
logAppend: true
path: /opt/arbiter/log/mongodb.log
storage:
journal:
enabled: true
dbPath: /data/arbiter/
directoryPerDB: true
wiredTiger:
engineConfig:
cacheSizeGB: 0.5
directoryForIndexes: true
collectionConfig:
blockCompressor: zlib
indexConfig:
prefixCompression: true
processManagement:
fork: true
pidFilePath: /opt/arbiter/pid/mongodb.pid
timeZoneInfo: /usr/share/zoneinfo
net:
port: 28300
bindIp: 127.0.0.1,$(ifconfig eth0|awk 'NR==2{print $2}')
replication:
oplogSizeMB: 1024
replSetName: shard2
sharding:
clusterRole: shardsvr
EOF
②、db02副本集配置
###master配置
cat >/opt/master/conf/mongod.conf<<EOF
systemLog:
destination: file
logAppend: true
path: /opt/master/log/mongodb.log
storage:
journal:
enabled: true
dbPath: /data/master/
directoryPerDB: true
wiredTiger:
engineConfig:
cacheSizeGB: 0.5
directoryForIndexes: true
collectionConfig:
blockCompressor: zlib
indexConfig:
prefixCompression: true
processManagement:
fork: true
pidFilePath: /opt/master/pid/mongodb.pid
timeZoneInfo: /usr/share/zoneinfo
net:
port: 28100
bindIp: 127.0.0.1,$(ifconfig eth0|awk 'NR==2{print $2}')
replication:
oplogSizeMB: 1024
replSetName: shard2
sharding:
clusterRole: shardsvr
EOF
###slave配置
cat >/opt/slave/conf/mongod.conf<<EOF
systemLog:
destination: file
logAppend: true
path: /opt/slave/log/mongodb.log
storage:
journal:
enabled: true
dbPath: /data/slave/
directoryPerDB: true
wiredTiger:
engineConfig:
cacheSizeGB: 0.5
directoryForIndexes: true
collectionConfig:
blockCompressor: zlib
indexConfig:
prefixCompression: true
processManagement:
fork: true
pidFilePath: /opt/slave/pid/mongodb.pid
timeZoneInfo: /usr/share/zoneinfo
net:
port: 28200
bindIp: 127.0.0.1,$(ifconfig eth0|awk 'NR==2{print $2}')
replication:
oplogSizeMB: 1024
replSetName: shard1
sharding:
clusterRole: shardsvr
EOF
###arbiter配置
cat >/opt/arbiter/conf/mongod.conf<<EOF
systemLog:
destination: file
logAppend: true
path: /opt/arbiter/log/mongodb.log
storage:
journal:
enabled: true
dbPath: /data/arbiter/
directoryPerDB: true
wiredTiger:
engineConfig:
cacheSizeGB: 0.5
directoryForIndexes: true
collectionConfig:
blockCompressor: zlib
indexConfig:
prefixCompression: true
processManagement:
fork: true
pidFilePath: /opt/arbiter/pid/mongodb.pid
timeZoneInfo: /usr/share/zoneinfo
net:
port: 28300
bindIp: 127.0.0.1,$(ifconfig eth0|awk 'NR==2{print $2}')
replication:
oplogSizeMB: 1024
replSetName: shard3
sharding:
clusterRole: shardsvr
EOF
③、db03副本集配置
###master配置
cat >/opt/master/conf/mongod.conf<<EOF
systemLog:
destination: file
logAppend: true
path: /opt/master/log/mongodb.log
storage:
journal:
enabled: true
dbPath: /data/master/
directoryPerDB: true
wiredTiger:
engineConfig:
cacheSizeGB: 0.5
directoryForIndexes: true
collectionConfig:
blockCompressor: zlib
indexConfig:
prefixCompression: true
processManagement:
fork: true
pidFilePath: /opt/master/pid/mongodb.pid
timeZoneInfo: /usr/share/zoneinfo
net:
port: 28100
bindIp: 127.0.0.1,$(ifconfig eth0|awk 'NR==2{print $2}')
replication:
oplogSizeMB: 1024
replSetName: shard3
sharding:
clusterRole: shardsvr
EOF
###slave配置
cat >/opt/slave/conf/mongod.conf<<EOF
systemLog:
destination: file
logAppend: true
path: /opt/slave/log/mongodb.log
storage:
journal:
enabled: true
dbPath: /data/slave/
directoryPerDB: true
wiredTiger:
engineConfig:
cacheSizeGB: 0.5
directoryForIndexes: true
collectionConfig:
blockCompressor: zlib
indexConfig:
prefixCompression: true
processManagement:
fork: true
pidFilePath: /opt/slave/pid/mongodb.pid
timeZoneInfo: /usr/share/zoneinfo
net:
port: 28200
bindIp: 127.0.0.1,$(ifconfig eth0|awk 'NR==2{print $2}')
replication:
oplogSizeMB: 1024
replSetName: shard2
sharding:
clusterRole: shardsvr
EOF
###arbiter配置
cat >/opt/arbiter/conf/mongod.conf<<EOF
systemLog:
destination: file
logAppend: true
path: /opt/arbiter/log/mongodb.log
storage:
journal:
enabled: true
dbPath: /data/arbiter/
directoryPerDB: true
wiredTiger:
engineConfig:
cacheSizeGB: 0.5
directoryForIndexes: true
collectionConfig:
blockCompressor: zlib
indexConfig:
prefixCompression: true
processManagement:
fork: true
pidFilePath: /opt/arbiter/pid/mongodb.pid
timeZoneInfo: /usr/share/zoneinfo
net:
port: 28300
bindIp: 127.0.0.1,$(ifconfig eth0|awk 'NR==2{print $2}')
replication:
oplogSizeMB: 1024
replSetName: shard1
sharding:
clusterRole: shardsvr
EOF
④、优化副本集
echo "never" > /sys/kernel/mm/transparent_hugepage/enabled
echo "never" > /sys/kernel/mm/transparent_hugepage/defrag
⑤、启动副本集
mongod -f /opt/master/conf/mongod.conf
mongod -f /opt/slave/conf/mongod.conf
mongod -f /opt/arbiter/conf/mongod.conf
ps -ef|grep mongod
⑥、初始化副本集
### db01 master节点初始化副本集
mongo --port 28100
rs.initiate()
等一下变成PRIMARY
rs.add("10.0.0.52:28200")
rs.addArb("10.0.0.53:28300")
rs.status()
### db02 master节点初始化副本集
mongo --port 28100
rs.initiate()
等一下变成PRIMARY
rs.add("10.0.0.53:28200")
rs.addArb("10.0.0.51:28300")
rs.status()
### db03 master节点初始化副本集
mongo --port 28100
rs.initiate()
等一下变成PRIMARY
rs.add("10.0.0.51:28200")
rs.addArb("10.0.0.52:28300")
rs.status()
3、config副本集配置
## 1.创建目录-三台机器都操作
mkdir -p /opt/config/{conf,log,pid}
mkdir -p /data/config/
## 2.创建手游账号拍卖地图配置文件-三台机器都操作
cat >/opt/config/conf/mongod.conf<<EOF
systemLog:
destination: file
logAppend: true
path: /opt/config/log/mongodb.log
storage:
journal:
enabled: true
dbPath: /data/config/
directoryPerDB: true
wiredTiger:
engineConfig:
cacheSizeGB: 0.5
directoryForIndexes: true
collectionConfig:
blockCompressor: zlib
indexConfig:
prefixCompression: true
processManagement:
fork: true
pidFilePath: /opt/config/pid/mongod.pid
timeZoneInfo: /usr/share/zoneinfo
net:
port: 40000
bindIp: 127.0.0.1,$(ifconfig eth0|awk 'NR==2{print $2}')
replication:
replSetName: configset
sharding:
clusterRole: configsvr
EOF
## 3.启动-三台机器都操作
mongod -f /opt/config/conf/mongod.conf
## 4.初始化副本集-db01操作即可
mongo --port 40000
rs.initiate()
等一下变成PRIMARY
rs.add("10.0.0.52:40000")
rs.add("10.0.0.53:40000")
rs.status()
4、mongos多节点配置
## 1.创建目录-三台机器都操作
mkdir -p /opt/mongos/{conf,log,pid}
## 2.创建配置文件-三台机器都操作
cat >/opt/mongos/conf/mongos.conf<<EOF
systemLog:
destination: file
logAppend: true
path: /opt/mongos/log/mongos.log
processManagement:
fork: true
pidFilePath: /opt/mongos/pid/mongos.pid
timeZoneInfo: /usr/share/zoneinfo
net:
port: 60000
bindIp: 127.0.0.1,$(ifconfig eth0|awk 'NR==2{print $2}')
sharding:
configDB:
configset/10.0.0.51:40000,10.0.0.52:40000,10.0.0.53:40000
EOF
## 3.启动-三台机器都操作
mongos -f /opt/mongos/conf/mongos.conf
## 4.登陆mongos-db01操作
mongo --port 60000
5、添加分片成员信息
## 1.登陆mongos添加shard成员信息-db01操作
mongo --port 60000
use admin
db.runCommand({addShard:'shard1/10.0.0.51:28100,10.0.0.52:28200,10.0.0.53:28300'})
db.runCommand({addShard:'shard2/10.0.0.52:28100,10.0.0.53:28200,10.0.0.51:28300'})
db.runCommand({addShard:'shard3/10.0.0.53:28100,10.0.0.51:28200,10.0.0.52:28300'})
## 2.查看分片成员信息
db.runCommand({ listshards : 1 })
6、分片配置
①、hash分⽚配置及测试
数据库开启分⽚
登录mongos
use到admin库
开启分片
db.runCommand( { enablesharding : "oldboy" } )
创建索引-⽚键
use oldboy
db.hash.ensureIndex( { id: "hashed" } )
集合开启hash分⽚
use admin
sh.shardCollection( "oldboy.hash",{ id: "hashed" } )
写入测试数据
⽣成测试数据
mongo --port 60000
use oldboy
for(i=1;i<10000;i++){db.hash.insert({"id":i,"name":"BJ","age":18});}
分⽚验证数据
shard1
mongo --port 28100
use oldboy
db.hash.count()
shard2
mongo --port 28100
use oldboy
db.hash.count()
shard3
mongo --port 28100
use oldboy
db.hash.count()
②、RANGE分片配置及测试
数据库开启分⽚
mongo --port 60000
use admin
db.runCommand( { enablesharding : "test" } )
创建索引-⽚键
use test
db.vast.ensureIndex( { id: 1 } )
集合开启range分⽚
use admin
db.runCommand( { shardcollection : "test.vast",key : {id: 1} } )
shardcollection #指定要分片的表
key #指定分片建
写入测试数据
⽣成测试数据
use test
for(i=1;i<2000000;i++){ db.vast.insert({"id":i,"name":"shenzheng","age":70,"date":new Date()}); }
db.vast.stats()
分⽚验证数据
shard1
mongo --port 28100
db.vast.count();
shard2
mongo --port 28100
db.vast.count();
shard3
mongo --port 28100
db.vast.count();
五、分片集群常用命令
(一)、列出分⽚所有详细信息
mongo --port 60000
db.printShardingStatus()
sh.status()
(1)所有分片节点信息
shards 段
(2)balancer状态
balancer 段
(3)开启分片功能的库和表信息
(二)、列出所有分⽚成员信息
mongo --port 60000
use admin
db.runCommand({ listshards : 1})
(三)、列出开启分⽚的数据库
mongo --port 60000
use config
db.databases.find({"partitioned": true })
(四)、查看分⽚的⽚键
mongo --port 60000
use config
db.collections.find().pretty()
(五)、删除分片节点
(1)确认blancer是否在工作
(2)删除shard2节点(谨慎)
db.runCommand( { removeShard: "shard2" } )
(六)添加分片节点
db.runCommand( { addshard : "sh3/10.0.0.51:38027,10.0.0.51:38028,10.0.0.51:38029",name:"shard3"} )
六、balancer管理
(一)、介绍
官方参考资料
mongos的一个重要功能,自动巡查所有shard节点上的chunk的情况,自动做chunk迁移。
mongodb在做自动分片平衡的时候,或引起数据库响应的缓慢,可以通过禁用自动平衡以及设置自动平衡进行的时间来解决这一问题。
(二)、blancer工作时间
1、自动运行,会检测系统不繁忙的时候做迁移。
2、在做节点删除的时候,立即开始迁移工作
3、balancer只能在预设定的时间窗口内运行
(三)、balancer管理命令
1、开启balancer
mongos> sh.stopBalancer()
2、关闭balancer
mongos> sh.startBalancer()
3、禁用balance
db.settings.update( { _id: "balancer" }, { $set : { stopped: true } } , true );
4、关闭某个集合的balance
sh.disableBalancing("students.grades")
5、打开某个集合的balance
sh.enableBalancing("students.grades")
6、查看某个集合的balance状态
db.getSiblingDB("config").collections.findOne({_id : "students.grades"}).noBalance;
7、自定义 自动平衡进行的时间段
(balancer工作时间段)
登录到mongos
切换配置库
设置balancer状态为true
sh.setBalancerState( true )
自定义工作时间
db.settings.update({ _id : "balancer" }, { $set : { activeWindow : { start : "3:00", stop : "5:00" } } }, true )
查询balancer时间
查看分片集群状态
删除balance 窗口
use config
db.settings.update({ _id : "balancer" }, { $unset : { activeWindow : true } })