转载自:Mongodb movePrimary_大数据_运维开发网_运维开发技术经验分享 (qedev.com)

move Primary

首先根据上一篇来短暂的回忆一下平衡器。Mongodb会开启一个线程balance专门负责数据的平衡工作,查看系统中所有的shard,发现不平衡的情况就选择将其中shard服务器的chunk迁移到其它服务器,让整个系统达到平衡

平衡策略

  • shard的数据大小超过了shard配置的数据大小,从中选择chunk迁移到别处
  • 找到shard中有违法tag规则的chunk,将这些chunk迁移到符合 tag规范的shard中
  • 找出tag中各个shard中chunk数,如果chunk数的差值大于阈值,从较多的shard移动chunk到较少的shard中

平衡器工作内容

  • 保持不同分片之间的数据平衡
  • 尽量最小化不同分片之间交互的数据块次数

主分片

在mongodb的分片集群中,创建的第一个分片会被默认为主分片,如果片键选择不合理,会导致集群不均衡,解决方法想到的有:

  • 使用moveChunk将数据移动到某个分片
  • 换片键,当然必须是没有创建的集合
  • 如果置换片键之后依旧失败。比如写入量太大,或者一下子import太多的数据。分享一个粗暴的方式,换主分片,因为数据都会大量的写入主分片,再开始移动。

在采用移动主分片之前,,我怀疑或许是我的片键设置的有问题,但是其实在数据量较小的情况下,一切运作良好,好吧,我开始利用其它的片键:

1.使用_id的哈希片键,且不论索引会占多大的空间,结果是数据依旧无法平衡

2.使用time,尽管升序片键不被推荐,但是可以采用半人工干预:开始使用了addShardTag,然后addTagRange,给平衡器指定特定时间范围数据位于某个shard上面,不过似乎没有起作用,其实分析一下,在原来可以均衡的片键下都没有成功,就平衡策略的第二种情形也是无法平衡的。

所以开始利用movePrimary力求数据全部写到这个主分片中,以降低原来主分片中磁盘的压力。其使用方法:

db.runCommand({"movePrimary":"test","to":"shard_1"})

上述命令将主分片移动到shard_1中。在移动的过程中或许会耗费非常多的时间,原因在于:

  1. 如果原来的主分片中存在大量的未分片的集合,在movePrimary中会将这部分集合全部移动过来,并创建索引。简直惊人!
  2. 创建索引的方式采用的是前台创建形式。所谓前台创建索引,所有的集合都将被锁住,包括读写,直到所有的索引都被创建完毕,是整个db的锁,所以,在移动的过程中不能有任何其他的读写操作。索引创建过程默认是前台方式,我们顺便了解下后台创建方式。后台创建过程不会影响其他的操作,但是其代价是速度很慢。特别的如果索引的大小大于可用的RAM,那么创建的过程将会非常漫长。
  3. 如果在移动的过程中没有禁止其他的操作,你进入一个未分片的集合,那么movePrimary也不会阻止对它的 读写,但是这个过程谁都无法保证最后的结果,行为未知。所以,在movePrimary之前,进行了一些操作:

  4. 检查所有的集合是否已经创建索引

  5. 检查集合是否已经分片,就此还写了个脚本
var getStats=function(name){
 var col_stats=db.getCollection(name).stats(); 
 if(col_stats.sharded) 
 { 
   db.shard_status.insert({"name":name,"shard":true}) 
 } 
 else 
 {
   db.shard_status.insert({"name":name,"shard":false}) 
  } 
}
  var nameArr=db.getCollectionNames(); 
  var i=0; 
  for(;i<nameArr.length;i++){
  getStats(nameArr[i]); 
 }
  1. 查看未分片的集合,对于一些小集合,我还是给予了分片, 避免db被锁住太长时间,查看CurrentOp,如果有createIndex等操作,请等待
  2. 删除shard_status,开始执行movePrimary命令,等待返回
  3. 在每个mongos使用
db.runCommand("flushRouterConfig")

*如果在使用movePrimary命令移动未分片集合,必须重新启动所有的mongos,或者使用flushRouterConfig,这个命令必须执行在对数据库的读写之前。它的本质告诉mongos这些集合位于新的分片中,更新mongos中元数据的配置。其实对于我们的操作,已经让所有的集合使用了分片,这个过程可以不做。

出现的问题

  1. movePrimary之后,目标分片无法显示对应的集合,发现在当前的主分片中这些集合的索引还没有创建,因为没有创建索引完毕,就开始向里面写入数据
  2. 报错 
  3. { "ok" : 0, "errmsg" : "clone failed" }

     

    进入到分片中的mongod,发现分片中出现相同的名字,这个过程发生在我试图切换回原来的主分片。官方也对此给出了结论,指出如果原来的主分片中存在相同的集合名称将会发生错误

  4. 性能影响

    如果原来的集合已经不平衡,切换主分片,集合依旧不平衡,数据分在某个分片中,将会影响查询的效率

    如果从一台较好的服务器切换到一个配置交差的服务器,其IO与平衡器的运行将会是一个问题,IO的增加,写入会降低,查询超时。只有那种主分片快满了,没有其他的当时下,短暂缓解主分片数据。

 posted on 2021-06-18 09:48  xibuhaohao  阅读(217)  评论(0编辑  收藏  举报