• Mongodb movePrimary(转载)


    转载自: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的增加,写入会降低,查询超时。只有那种主分片快满了,没有其他的当时下,短暂缓解主分片数据。

  • 相关阅读:
    leetcode 141. Linked List Cycle
    leetcode 367. Valid Perfect Square
    leetcode150 Evaluate Reverse Polish Notation
    小a与星际探索
    D. Diverse Garland
    C. Nice Garland
    数的划分(动态规划)
    平衡二叉树(笔记)
    1346:【例4-7】亲戚(relation)
    1192:放苹果(dp + 搜索)
  • 原文地址:https://www.cnblogs.com/xibuhaohao/p/14898267.html
Copyright © 2020-2023  润新知