一、简介
1. 分片集群简介
-
1.分片原因
分片集群是为了解决单节点存在的CPU和存储,IO的瓶颈问题,将原来存储在单个mongo实例中的数据,按照一定的规则分散存储在多个mongo实例中,每个mongo中只存储一部分数据,对数据进行读写时仅需要访问存储这条数据的mongo分片节点即可。
-
2.分片优势
-
分片性能有极大提升,且方便扩展
-
集群对客户端透明,客户端不需要知道分片信息,客户端不需要额外的配置
-
每个分片都可以使用副本集群保障分片的高可用,从而可以保障整个分片集群高可用
-
-
3.分片劣势
分片集群架构与单实例和副本集群相比复杂很多,运维成本要高一些
2. 分片集群角色
-
1.config server
配置节点,存储集群的配置信息,分片数据的路由信息等,为保障高可用,默认最少需要三个config server节点的副本集群
-
2.mongos
路由节点,提供对外访问接口,所有客户端的请求通过mongos路由到具体的数据节点,mongos节点不存储任何信息,通过config server获取分片信息。一般有多个mongos节点,但不需要配置为集群,可以和客户端部署在同一个节点上,每个客户端部署一个mongos
-
3.mongod
mongod即数据存储的节点,一般有多个mongod节点,存储不同的分片数据。可以将一个副本集群作为一个分片节点,保障分片的高可用
3. 分片集群架构
-
1.集群架构
-
客户端通过mongos读写数据
-
mongos通过config server获取分片信息
-
mongos找到对应的分片插入或读取数据
-
每一个分片可以是单个mongo实例也可以是一个副本集群,下图画的都是副本集群
-
-
2.分片存储
-
chunks:
chunk
是数据存储单元,mongod
存储数据时把多条数据存储到同一个chunk
,当一个chunk
大于配置中的chunk size
时,会把该chunk
切分成更小的chunk
, -
balancer
balancer是一个后台进程,复制chunk迁移,从而均衡各个mongod的负载。
-
-
3.chunk大小
chunk size
默认64M
,可以调整配置中的chunk size- chunk size越小,chunk的分裂次数越多,数据分布越均匀。反之,chunk的分裂和迁移会少,但可能导致数据不均匀
- chunk自动分裂只会在数据写入时发生,如果chunk size调小,不会立即触发chunk的分裂和迁移,需要一定时间达到指定的大小
- chunk只会分裂,不会合并,也就是说即使将chunk size调大,现有的chunk数量也不会变少
4. 分片键
-
1.分片键介绍
-
mongo数据的分布是以分片键为拆分的依据,因此分片键至关重要。
-
mongo的分片使用基于范围的或是基于哈希的
-
-
2.分片键特点
- 分片键确定后不可改变
- 分片键必须有索引
- 分片键最大为512bytes
- 无法在设置了分片的collection上插入无分片键的文档
- 如果查询条件中没有包含分片键,那么查询性能会很糟糕
-
3.基于范围的分片
按照分片键的范围把数据分为不同部分,相似或连续的分片键很可能存储在同一个数据块中。
基于范围的分片键查询时mongos可以很高效的知道查询的数据在哪一个数据块中,但范围分片也可能会导致数据分布不均匀,或是热点数据集中在个别数据块中的现象。比如对于自增的字段作为分片键,新写入的数据都会集中在最后一个数据块中。
-
4.基于哈希的分片
基于哈希的分片,mongo对分片键计算一个哈希值,并用这个哈希值确定数据分布在哪个数据块,因此数据的分布更均匀,相似的分片键并不会被写入到相同的数据块中。
哈希分片解决了范围分片的问题,但由于数据太过分散,当执行范围查询时可能需要后端的所有节点都执行查询操作然后进行合并排序后才能得到结果
-
5.分片键的选择
-
单调升序的分片键(递增)
相似或连续数据集中,范围查询可以快速定位数据块,但可能导致数据分布不均,最后一个数据块是写热点
-
随机分片键
比如md5,哈希值等,数据分布均匀,IO分布均匀,但会产生大量的随机IO,磁盘负担大
-
混合分片键
组合升序分片键和随机分片键,设置合理的分片算法,使数据大范围上集中,但又不会因为太集中而产生局部热点,比如按照月份范围分片,和一个md5值哈希分片,同一个月份的数据集中在一个“大局部”,而md5可以使数据在“大局部”中的均匀分布,不至于产生“小局部”热点。
-
使用常用的查询相关的字段作为分片键,并且能包含唯一字段
-
二、分片集群搭建与测试
1. 环境介绍
我们就按照上面架构图中的架构搭建一个全高可用的分片集群
这里是在一台机器上启动了多个mongo实例,实际生产环境中需要分开
-
配置节点副本集群
副本集名称 角色 端口 数据文件路径 config config server 20001 /data/mongo/20001/ config config server 20002 /data/mongo/20002/ config config server 20003 /data/mongo/20003/ -
第一个分片的副本集群
副本集名称 角色 端口 数据文件路径 shard1 mongod 30001 /data/mongo/30001/ shard1 mongod 30002 /data/mongo/30002/ shard1 mongod 30003 /data/mongo/30003/ -
第二个分片的副本集群
副本集名称 角色 端口 数据文件路径 shard2 mongod 40001 /data/mongo/40001/ shard2 mongod 40002 /data/mongo/40002/ shard2 mongod 40003 /data/mongo/40003/ -
第三个分片的副本集群
副本集名称 角色 端口 数据文件路径 shard3 mongod 50001 /data/mongo/50001/ shard3 mongod 50002 /data/mongo/50002/ shard3 mongod 50003 /data/mongo/50003/ -
路由节点
路由节点不需要副本集,单节点即可
角色 端口 数据文件路径 mongos 60001 /data/mongo/60001/
2. 搭建配置节点的副本集群
-
1.创建mongo用户
useradd mongo echo "mongo" | passwd --stdin mongo
-
2.解压mongo二进制文件
tar -xzvf mongodb-linux-x86_64-rhel70-4.2.3.tgz -C /usr/local/ cd /usr/local/ mv mongodb-linux-x86_64-rhel70-4.2.3 mongodb chown mongo:mongo mongodb/ -R
-
3.修改环境变量
- 若允许所有用户都可以使用mongo命令则在
/etc/profile
中加入如下行,然后执行source /etc/profile
生效 - 若仅允许mongo用户使用mongo则切换到mongo用户,在mongo用户家目录中的
.bash_profile
文件中加入如下行,然后source ~/.bash_profile
生效
export PATH=/usr/local/mongodb/bin:$PATH
- 若允许所有用户都可以使用mongo命令则在
-
4.创建所需的数据目录
mkdir -p /data/mongo/2000{1,2,3}/{data,log} chown mongo:mongo -R /data/mongo
创建完成后目录如下:
/data/mongo/20001 ├── data └── log /data/mongo/20002 ├── data └── log /data/mongo/20003 ├── data └── log
-
5.在20001,20002,20003三个目录下新建
mongo.conf
配置文件,文件内容如下,每个实例修改端口和路径配置# /data/mongo/20001/mongo.conf dbpath=/data/mongo/20001/data logpath=/data/mongo/20001/log/mongo.log fork=true port=20001 replSet=config #副本集的名称,三个节点一致 configsvr=true #表示这是个配置节点 # /data/mongo/20002/mongo.conf dbpath=/data/mongo/20002/data logpath=/data/mongo/20002/log/mongo.log fork=true port=20002 replSet=config configsvr=true # /data/mongo/20003/mongo.conf dbpath=/data/mongo/20003/data logpath=/data/mo