mongodb 集群维护
1 简介
谈谈mongodb的集群架构
2 常用的维护命令
1 查看状态 sh.status()
1 version
2 shards: 分片集群shard成员
3 balancer: 平衡器的相关状态:运行状态 尝试次数
平衡器 sh.setBalancerState(true) 开启
sh.stopBalancer() 关闭
sh.getBalancerState() 查看状态
4 database: 注意几个值
1 partitioned:false代表没有采用分片
2 primary s1 代表在s1片上 如果有分片 会列出分片信息 比如 shard key 和chunks
2 config服务库
db.collection.status()查看分片信息
3 如何开启分片
1 库开启分片功能
use admin && db.runCommand( { enablesharding : "test" } )
2 集合片键加索引
use test && db.vast.ensureIndex( { id: 1 } )
3创建片键
use admin && db.runCommand( { shardcollection : "test.vast1",key : {id: 1,name:1} } )
4 数据插入测试
for(i=0;20000<i<40000;i++){ db.vast1.insert({"id":i,"name":"clsn","age":70,"date":new Date()}); }
db.vast.stats()
5 相关总结:
1 片键必须是集合文档中的单索引或者是混合索引
2 片键添加方法sh.shardCollection( namespace, key ) namespace 参数是 database.collection
3 片键一经定义后是无法修改的,定义后有且只有一个,索引本身有唯一性
4 方法 db启动分片->分片加索引->collection启动分片
4 谈分片
1 理想分片:
目标:将插入数据均匀分布到各个分片上;保证CRUD操作能够利用局部性;有足够的粒度进行块拆分。
影响:增加可用的RAM,增加可用磁盘空间,减轻单台服务器的负载,处理单个mongod无法承受的吞吐量
分片场景
1 业务上线时已指定好合理的分片字段,后期不用再更改
需要制定合理的分片规则
2 业务上线制定不合理的分片字段,后期需要重新制定分片规则
需要mongodump出数据,再制定分片,mongorestore导入
3 业务上线时并没有指定任何分片字段,后期需要制定分片规则
需要指定合理的分片规则,然后执行分片命令,这里需要的时间比较长,建议后台执行
可能出现的问题
1 数据分配不均匀,常见于片键的选择不合理 可以通过sh.status() shard的数量对比来判断是否分配不均匀
2 在move chunk过程中,查询的数据不准确
2 分片分类
范围分片
eg:id,date等带有明显顺序的
优势 如果使用升序片键,那么数据物理上会是连续的,有利于基于范围的查询
缺点 1 降低写入性能,空间块利用率不高 2 需要大量的move chunk,因为降低了数据均衡处理能力
启用命令
db.runCommand( { shardcollection : "test.vast1",key : {date:1} } )
Hash 分片
eg:是用户名 邮件地址 udid(唯一设备标识符) md5散列值 或者是数据集中其他一些没有规律的键
优势 能非常好的平均分配到各个shard上
缺点 1 查询性能不高,需要与磁盘更多的IO交互
启用命令
db.runCommand( { shardcollection : "test.vast2",key : {date:"hashed"} } )
联合分片
随机值+范围值组成的联合索引
推荐
注意:
1 采用hash分片的策略chunk总数远远小于升序分片的个数
2 无论采用什么分片策略都要考虑业务本身,业务快是唯一的条件
5 谈谈move chunk
触发条件
1 写入数据时,会先创建一个min,max的chunk,随着数据量不断增加,超过分裂阈值,就会触发chunk分裂
2 当各个分片的chunk分布不均衡,会触发移动过程
决定机制
Balancer在工作时,会根据shardtag,集合的chunk数量,shard间的chunk数量差值来决定是否需要迁移
迁移过程
1 原分片开始启动moveChunk命令,在移动的过程中,所有的操作还会指向原来的分片
2 目标分片开始创建所需要的索引,在3.0以后,moveChunk需要在移动之前,目标分片中存在所有的索引,可以理解为先在目标分片中创建这个索引。
3 目标分片开始向原分片请求数据,并复制数据
4 当数据全部写入到目标分片中,目标分片连接并更新config数据库对应的块信息
5 最后,原分片将这部分块删除。
6 迁移完成标记sh.status()的balance
"state" : 0, #0:非活动状态,1:正在获取,但还没有执行,2:正在均衡,迁移,有锁
Migration Results for the last 24 hours
success 数值不断增长,代表正在进行move chunk
手动触发迁移
希望分隔一个已经存在数据的集合,这个集合所有的数据都在一个分片中
手动触发命令
Sh.moveChunk({“test.vfast1”,{id},”shard_2”})
参数1为namespace 参数2为片键名称 参数3为shard实例名
日志
moving chunk 可以在route.log中观测到
类似于 [Balancer] moving chunk ns
6 集群自动扩容
1 无论何种分片方式都可以实现shard的自动扩容
2 采用db.runCommand({addshard)即可
3 等待move chunk完成
7 相关错误汇总
1 MongoDB chunk too big to move
1 sh.stopBalancer() //关闭平衡器
2 use config && db.chunks.find({jumbo:true}) //查找大块
3 sh.splitAt("db.collection", {shardkye:"拆分的临界值"})//进行手动拆分
4 sh.moveChunk("db.collection", {shardkey:"shardkey所在的块"}, "需要移动的目标分片ID");//进行手动迁移
5 sh.startBalancer()//打开平衡器
总结 2.4.6版本以上,在这个版本里修复了SERVER-9365的问题,能平均地拆分数据块。值得注意的是,由于有的数据块包含有非常多的文档,将会花一定的时间将这些大数据块拆分成可以迁移的小数据块。在这个过程中,您可能还会看到”chunk too big to move”的错误。
8 管理难度
1单副本集(易)
2集群简单分片(中)
3集群复杂分片(难)
补充一点 能简单就简单,不要硬上集群,哪怕上了集群,要简单分片,否则管理难度会成倍增大
9 备份补充
mongo --eval "sh.stopBalancer()"
mongodump -o $TAR_FILE_PATH
mongo --eval "sh.setBalancerState(true)"