zoukankan      html  css  js  c++  java
  • 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的增加,写入会降低,查询超时。只有那种主分片快满了,没有其他的当时下,短暂缓解主分片数据。

  • 相关阅读:
    109 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 03 新增功能及实现 05 问题解析--通过一个方法完成学生和专业的双向关联
    108 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 03 新增功能及实现 04 问题解析--数组未实例化造成的空指针异常
    107 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 03 新增功能及实现 03 编写方法完成学生个数统计功能
    106 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 03 新增功能及实现 02 新增属性完成学生信息存储
    105 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 03 新增功能及实现 01 新增需求及分析
    session与cookie的区别和联系
    session和cookie的区别
    Web服务器主动推送技术
    webSocket的场景应用
    TCP、Http和Socket 优劣比较
  • 原文地址:https://www.cnblogs.com/xibuhaohao/p/14898267.html
Copyright © 2011-2022 走看看