MongoDB--chunk的分裂和迁移

MongoDB–chunk的分裂和迁移

文章目录

    • MongoDB--chunk的分裂和迁移
      • 一:关于chunk的分裂和分块简介
      • 二:chunk的分裂
        • 1. chunk分裂的逻辑
        • 2. 修改chunk的大小
      • 三:chunk的迁移
        • 1. 根据shard tag迁移
        • 2. 根据shard之间的chunk数量迁移
        • 3. removeShard触发迁移
        • 4. 手动移动块
      • 四:对分裂和迁移的管理

一:关于chunk的分裂和分块简介

启用分片之后,数据会以chunk为单位(默认64MB,大小是1~1024MB之间)根据片键(shardKey,按照自己指定的字段作为片键)均匀的分散到后端1或多个shard上。

每个database会有一个主分片(primary shard),在数据库创建时分配。database下启用分片(即调用shardCollection命令)的集合,刚开始会生成一个[minKey, maxKey]的chunk,该chunk初始会存储在primary shard上,然后随着数据的写入,不断的发生chunk分裂及迁移。初始的minkey和maxkey是无穷大和无穷小。

MongoDB--chunk的分裂和迁移_第1张图片

二:chunk的分裂

1. chunk分裂的逻辑

chunk的默认大小是64MB,达到这个阈值就会发生分裂。

int ChunkManager::getCurrentDesiredChunkSize() const {
    // split faster in early chunks helps spread out an initial load better
    const int minChunkSize = 1 << 20;  // 1 MBytes
    int splitThreshold = Chunk::MaxChunkSize;  // default 64MB
    int nc = numChunks();
    if (nc <= 1) {
        return 1024;
    } else if (nc < 3) {
        return minChunkSize / 2;
    } else if (nc < 10) {
        splitThreshold = max(splitThreshold / 4, minChunkSize);
    } else if (nc < 20) {
        splitThreshold = max(splitThreshold / 2, minChunkSize);
    }
    return splitThreshold;
} 
bool Chunk::splitIfShould(OperationContext* txn, long dataWritten) const {
    dassert(ShouldAutoSplit);
    LastError::Disabled d(&LastError::get(cc()));
    try {
        _dataWritten += dataWritten;
        int splitThreshold = getManager()->getCurrentDesiredChunkSize();
        if (_minIsInf() || _maxIsInf()) {
            splitThreshold = (int)((double)splitThreshold * .9);
        }
        if (_dataWritten < splitThreshold / ChunkManager::SplitHeuristics::splitTestFactor)
            return false;
        if (!getManager()->_splitHeuristics._splitTickets.tryAcquire()) {
            LOG(1) << "won't auto split because not enough tickets: " << getManager()->getns();
            return false;
        }
        ......
}

2. 修改chunk的大小

1.连接mongos

2.use config

3.db.settings.save({_id:“chunksize”,value:64}) //单位是MB

注意:

  • 自动分裂只在插入的时候生效
  • 如果降低了块的大小,那么可能需要一段时间才能将所有块分割为新的大小
  • 分裂不能被取消
  • chunk只会分裂,不会合并,所以即使将chunkSize改大,现有的chunk数量不会减少,但chunk大小会随着写入不断增长,直到达到目标大小。
  • 块大小的允许范围是1到1024 mb(包括1024 mb)

修改chunk大小的影响:
MongoDB--chunk的分裂和迁移_第2张图片

三:chunk的迁移

balancer(均衡器)负责数据的迁移,它会周期性的检查分片间是否存在不均衡,如果存在就会开始迁移。chunk迁移是主动进行的。

1. 根据shard tag迁移

MongoBD sharding支持shard tag特性,用户可以给shard打上标签,然后给集合的某个range打上标签,MongoDB会通过balancer的数据迁移来保证「拥有tag的range会分配到具有相同tag的shard上」

2. 根据shard之间的chunk数量迁移

int threshold = 8;
if (balancedLastTime || distribution.totalChunks() < 20)
    threshold = 2;
else if (distribution.totalChunks() < 80)
    threshold = 4;
集合chunk数量 迁移阈值
[1,20) 2
[20,80) 4
[80,max] 8

针对所有启用分片的集合,如果「拥有最多数量chunk的shard」与「拥有最少数量chunk的shard」的差值超过某个阈值,就会触发chunk迁移; 有了这个机制,当用户调用addShard添加新的shard,或者各个shard上数据写入不均衡时,balancer就会自动来均衡数据。

mongos> db.chunks.find().count()
7

我这里chunk的个数是7,如果两个shard的chunk差值超过2就会发生迁移

3. removeShard触发迁移

还有一种情况会触发迁移,当用户调用removeShard命令从集群里移除shard时,Balancer也会自动将这个shard负责的chunk迁移到其他节点

4. 手动移动块

>use config

//Sh.moveChunk({“test.collecton”,{query},”shard_1”}),参数1:集合,参数2:查询条件,参数3:移动到那个分片
>sh.moveChunk("test.user",{"user_id":NumberLog("28179147024124")},shard2)

如果出现某个块的大小超出了系统指定了最大值,mongos则会拒绝移动这个块。可以使用splitAt命令对块拆分

>sh.splitAt({"user_id":NumberLog("28179147024124")})

四:对分裂和迁移的管理

1.建议chunkSize大小保持默认值

2.chunkSize太大会导致迁移变少,数据不均匀;chunksize太小会造成jumbo chunnk(shardKey 的某个取值出现频率很高,这些文档只能放到一个chunk里,无法再分裂)

3.在使用shardCollection对集合进行分片时,如果使用hash分片,可以对集合进行「预分片」,直接创建出指定数量的chunk,并打散分布到后端的各个shard,指定numInitialChunks参数在shardCollection指定初始化的分片数量,该值不能超过8192。

4.Balancer能动态的开启、关闭,Blancer能针对指定的集合来开启、关闭,Balancer支持配置时间窗口,只在制定的时间段内进行迁移

原文参考:https://blog.csdn.net/joy0921/article/details/80131276

你可能感兴趣的:(MongoDB)