mongo分片部署
分片目的
高数据量和吞吐量的数据库应用会对单机的性能造成较大压力,大的查询量会将单机的CPU耗尽,大的数据量对单机的存储压力较大,最终会耗尽系统的内存而将压力转移到磁盘IO上
为了解决这些问题,基本有两个基本方法:垂直扩展和水平扩展。
- 垂直扩展:增加更多的CPU和存储资源来扩展容量。
- 水平扩展:将数据集分布在多个服务器上,水平扩展即分片。
MongoDB中的分片
MongoDB通过配置分片集群来支持分片,一个分片集群包括以下几个组件:分片,查询路由,配置服务器
- 分片:用来春初数据,为了提供系统可用性和数据一致性,一个生产环境 的分片集群,通常每个分片是一个副本集
- 查询路由:指客户端应用访问每个分片的路径
- 配置服务器:存储集群的元数据,这些数据包含了集群数据集到各个分片的映射关系。查询路由就是通过这些眼数据到特定的分片上执行指定的数据组操作。
数据划分
MongoDB的数据划分是以集合集合为标准。分片通过shard key来划分集合的数据。
**shard key:**为了对集合分片,需要指定一个shard key。shard key既可以是集合的每个文档的所以字段也可以是及合作每个文档都有的组合索引字段。MongoDB将shard keys 值按照块(chunks)划分,并且均匀的将这些chunks分配到各个分片上。MongoDB使用基于范围划分或者基于散列划分chunks.
- 基于范围划分:
- MongoDB通过shard key值将数据集划分到不同的范围就称为基于范围的划分。对于数值型的shard key:可以虚构一条虫负无穷的直线(可以理解为X轴),每个shard key值都落在这条直线的某个点上,然后MongoDB把则条线划分为许多更小的没有重复的范围称为块,一个chunk会议室某些最小值到最大值的范围。
- 基于散列划分 MongoDB计算每个字段的hash值,然后用这些hash值建立chunks. 基于范围和基于散列划分的性能比较:
基于范围划分对于范围查询比较高效。假设在shard key上进行范围查询,查询路由很容易能够知道哪些块与这个范围重叠,然后把相关查询按照这个路线发送到仅仅包含这些chunks的分片。但是基于范围划分很容易导致数据不均匀分布,这样会削弱分片集群的功能。例如当shard key是个成直线上升的字段,如时间。那么,所有在给定时间范围内的请求都会映射到相同的chunk,也就是相同的分片上。这种情况下,小部分的分片将会承受大多数的请求,那么系统整体扩展并不理想。
相反的,基于散列划分是以牺牲高效范围查询为代价,它能够均匀的分布数据,散列值能够保证数据随机分布到各个分片上。
- 使用标签来自定义数据的分布 MongoDB允许DBA们通过标签标记分片的方式直接平衡数据分布策略,DBA可以创建标签并且将他们与shard key值的范围进行关联,然后分配这些标签到各个分片上,最终平衡器转移带有标签标记的数据到对应的分片上,确保集群总是按照标签描述的那样进行数据分布。标签是控制平衡器行为以及集群中分块的主要方法。
维持数据平衡
新加入的数据以及服务器都会导致集群数据分布不平衡,MongoDB采用两种方式确保数据分布的平衡;
- 拆分 拆分是一个后台进程,防止块变得太大,当一个块增长到指定块大小时候,拆分进程就会把块一分为二,整个拆分过程是搞笑的,不会涉及到数据的迁移等操作。
- 平衡 平衡器是一个后台进程,管理块的迁移。平衡器能够运行在集群任何的mongod实例上。当集群中数据分布不均匀时候,平衡器就会将某个分片中比较多的块迁移到拥有块比较少的分片中,知道数据分片平衡为止。
- 从集群中增加和删除分片 添加新分片到集群中会产生数据不平衡,因为新分片中没有块,当MongoDB开始迁移数据到新分片中时,等到数据分片平衡恐怕需要点时间。
当删除一个分片时,平衡器将会把分片中所有块迁移到另一个分片中,在完成这些迁移并更新元数据后,你就可以安全的删除分片了。
片键
- 在分发集合中文件时,mongodb的分区使用的收集片键关键,在片键由存在目标集合中的每个文档中的一个不可变或多个字段
- 在分割集合的时候选择片键,f分片键完成之后是不能更改的,分片集合只能有1个片键,到片键的非空集合,集合必须有一个索引,与片键启动,对于空空集合,如果集合尚未具有指定分片键的相关索引,则Mongodb会创建索引
- 分片键的选择会影响分片集群的性能和效率以及可伸缩性,具有最佳可能的硬件可以通过分片达到瓶颈,片键和其支持指数的选择也可以影响数据的拆分,但集群可以使用
- 片键决定了集群中一个集合的文件咋不同的片键中的分布,片键字段必须被索引,且在集合中的每条记录都不能为空,可以是单个字段或者是复合字段
- Mongodb使用片键的范围是吧数据分布在分片中,每个范围,又称为数据块,定义了一个不重叠的片键范围Mongodb把数据块与他们存储的文档分布到集群中的不同分布中,当一个数据块的大小超过数据块最大大小的时候,Mongodb会宜聚片键的范围将数据块分裂为更小的数据块
部署步骤
1.下载mongo安装包(官网下载)
2.创建对应的data和log 目录
3.编写配置文件
配置config server
config.conf
logpath=/home/mongodb/config/log/config.log
pidfilepath=/home/mongodb/config/config.pid
logappend=true
port=21000
fork=true
dbpath=/home/mongodb/config/data
configsvr=true # 在配置文件添加此项就行
oplogSize=512
replSet=config
配置mongos
mongos.conf
注意:config server必须是复制集才行,mongos才能启动成功,所以先配置好config server 再启动,下文将介绍config 配置初始化
logpath=/home/mongodb/mongos/log/mongos.log
pidfilepath=/home/mongodb/mongos/mongos.pid
logappend=true
port=21017
fork=true
configdb=config/192.168.1.93:21000 #如果有多个mongo config的话就用逗号分隔开
配置shard
shard.conf
logpath=/home/mongodb/shard/log/shard.log
pidfilepath=/home/mongodb/shard/shard.pid
directoryperdb=true
logappend=true
port=21001
fork=true
dbpath=/home/mongodb/shard/data
oplogSize=512
replSet=sha
shardsvr=true
启动mongo
config
mongod -f /home/mongodb/conf/config.conf
shard
mongod -f /home/mongodb/conf/shard.conf
mongos
mongod -f /home/mongodb/conf/mongos.conf
初始化mongo
config
config = { _id:"config",members:[ {_id:0,host:"conf1:30000"}, {_id:1,host:"conf2:30001"}, {_id:2,host:"conf3:30002"}] } #定义副本集
rs.initiate(config) #初始化副本集
shard
sha = { _id:"sha",members:[ {_id:0,host:"sha1:60000"}, {_id:1,host:"sha2:60001"}, {_id:2,host:"sha3:60002"}]}
rs.initiate(sha)
开始分片
sh.status() #查看分片状态
- 添加shard副本
sh.addShard("shard/shard1:21001")
同理再添加其他分片
- 对某个数据库使用分片
sh.enableSharding("lib")
- 对集合分片
在lib数据库的traffic集合中创建了dt升序的片键
sh.shardCollection("lib.traffic",{dt:1})
选择sharing kes'注意点
-
考虑应该在哪里储存数据?
-
应该在哪里读取数据?
-
sharding key 应该是主键
-
sharding key 应该你能尽量保证避免分片查询
平衡器(Balancer)
开启Balancer之后,chunks之后会自动均分
sh.startBalancer()
设置Balancer进程运行时间窗口 默认情况ixaBalancing进程在运行时为降低Balancing进程对系统的影响,可以设置Balancer进程的运行时间窗口,让Balancer进程在指定时间窗口操作
#设置时间窗口
db.settings.update({ _id : "balancer" }, { $set : { activeWindow : { start : "23:00", stop : "6:00" } } }, true )
# 查看Balancer时间窗口
mongos> db.settings.find();
{ "_id" : "balancer", "activeWindow" : { "start" : "23:00", "stop" : "6:00" }, "stopped" : false }
mongos> sh.getBalancerWindow()
{ "start" : "23:00", "stop" : "6:00" }
# 删除Balancer进程运行实际那窗口
db.settings.update({ "_id" : "balancer" }, { $unset : { activeWindow : 1 }});
预分片
#对集合进行分片
sh.shardCollection("lib_shard.traffic1",{"dt":1})
#按月分片
for(var i=1; i<=12;i++){sh.splitAt("lib_shard.traffic1",{"dt":new Date(y,i+9,1)})}
修改chunk大小
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 大小会随着写入不断增长,直到达到目标大小。
# 修改chuck大小命令 (默认是64MB,取值范围是1 MB 到 1024 MB.)
db.settings.save( { _id:"chunksize", value: <sizeInMB> } )