在了解平衡之前,或许有必要好好的了解下分裂与迁移
写入数据时,会先创建一个min,max的chunk,随着数据量不断增加,超过分裂阈值,就会触发chunk分裂,当各个分片的chunk分布不均衡,会触发移动过程。Balancer在工作时,会根据shardtag,集合的chunk数量,shard间的chunk数量差值来决定是否需要迁移。
如果两个shardchunk数超过某个阈值,会触发chunk移动,其阈值如下:
最小值最大值阈值12022040480max8从上面来看,如果是均衡的一个集群,分片之间的chunk数量差值不会超过8。所以,只有超过2个的chunk,才会开始移动,当然这句话有点多余。
迁移chunk过程包括两个内部通信协议:
复制数据,复制过程中改变的内容
确保所有参与迁移的组成部分,目的shard,源shard,config server都确定迁移完成
原分片开始启动moveChunk命令,在移动的过程中,所有的操作还会指向原来的分片
目标分片开始创建所需要的索引,在3.0以后,moveChunk需要在移动之前,目标分片中存在所有的索引,可以理解为先在目标分片中创建这个索引。
目标分片开始向原分片请求数据,并复制数据
当数据全部写入到目标分片中,目标分片连接并更新config数据库对应的块信息
最后,原分片将这部分块删除。
在splitchunk时,只有config信息发生改变,chunk数增加,其基本的数据信息不发生变化。Balancer能够针对指定的集合来开启,关闭,支持配置时间窗口,在指定的时间段内进行迁移。
官方建议我们在特殊的情况下才使用moveChunk,但是,在一些情况下,mongodb不能创建足够的chunk或者快速的分发数据到chunk中,尤其是在高吞吐量的情况下。比如:
你希望分隔一个已经存在数据的集合,这个集合所有的数据都在一个分片中
如果你想要接收大量数据到集群中但是它处于不平衡下,或者接收到大量的数据造成数据的不平衡。比如,自增或者自降的shard key,会造成很多数据写入到一个单独的块中。
我们数据库在切换过来之后,初期将之前的数据进行了还原,短时间内导入了大量的数据,too young too simple,集群很不均衡。
Sh.moveChunk({“test.collecton”,{query},”shard_1”})其中,第一个参数为集合的命名空间及集合名称,query为查询的片键,这个函数还有
一个调用方式,详见官方文档,后面的为指定的分片。
1.如果moveChunk过程中,在集合的块中有其他的元数据发生了变化,那么会返回一个meta data的错误。
2.在移动的过程中虽然分块的shard已经在目标分片,但是除了在目标分片中创建索引,其原来的索引还在,没有被删除,所以如果手动移动的过程中,索引的空间将不断增加。这个与movePrimary的未分片的集合一样,需要建立索引。
3.有个疑问,这个索引不断增加,索引的数据是维护在哪里的?是随着数据的分片走的吗?能不能删除原来的索引?如果索引空间不断增加,所造成的影响,在查询的时候最好是所有的索引都加入内存,那么如果这样子的话,是不是造成索引多重加入?