MongoDB shardCollection介绍
1. 特性概述
对于mongodb分片集群来说,在默认情况下一个集合的数据都是存储在一个shard上。如果一个集合的数据量非常大,就会导致不同shard之间的业务负载有很大差异,这种情况显然是不合理的。所以大多数情况下都应该对集合开启分片,也就是执行shardCollection,这个命令的作用就是开启集合在不同shard之间的自动均衡。
2. 命令原理
shardCollection命令的基本要素是指定集合(namespace)和片键(key);片键是集合文档中的一个字段,片键字段所对应的值就是collection切分为不同chunk的依据。shard概念及片键选择建议请参考https://docs.mongodb.com/manual/sharding/
3. 约束
l 如果是新集合,选择片键后,mongo会在片键上创建索引。
l 一个集合不能同时选择多个片键。
l 不能update片键对应字段。
l 如果集合不为空,则在shardCollection之前需要在对应片键上提前创好索引。
l 分片集合不能在片键以外的字段创建唯一索引。
l 选择片键时不能有片键以外的字段存在唯一索引。
4. 处理逻辑
shardCollection命令在mongos上执行,命令入口cluster_shard_collection_cmd.cpp:
1) cluster_shard_collection_cmd.cpp的run方法:
可以看到命令内部有一个是否retry的判断,后面部分判断和rollback的逻辑都是为了命令重试的场景
因为创建片键的限制比较多,所以校验逻辑也会比较长。除了命令入参的合法性校验以外的核心就是usefulIndex校验。因为对于有数据的集合,在片键上有合法索引才能shardCollection。上面是入参校验。涉及到的两个知识点:collation参考 http://www.mongoing.com/archives/3912, view参考 http://www.mongoing.com/archives/3502。
合法索引校验。校验完成后会调用harding_catalog_client_impl.cpp的shardCollection方法。
2) sharding_catalog_client_impl.cpp的shardCollection方法:
该方法主要用来:
l 获取集合的分布式锁,防止shardCollection过程中集合被删除或重复调用shardCollection。
l 在config.changelog中写入记录shardCollection.start。
l 调用config的shard_collection.cpp的run方法。
3) shard_collection.cpp的run方法:
该方法有两个主要分支,如果是新集合直接走run_normal方法,如果不是新集合走shardCollectionExist2方法。
l 先看run_normal方法的实现:
主要工作是创建集合和索引的元数据
对于hash分片的新集合有一个特殊处理,这种场景会先算出一批拆分点,并同时创出一批chunk(numShards-1)。拆分原理是把hash值的范围进行均分(-MIN long, +MAX long),long类型是64位,所以hash的最大值是2^64,这样做的好处是可以一开始就保证数据的均匀分布,减少迁移。如果不符合该条件则调用_create_one_chunk方法创建一个chunk。
l 接着看shardCollectionExist2方法的实现:
可以发现对有数据集合执行shardCollection的逻辑要复杂一些
一开始也是执行run_normal方法,但这种场景下入参newCmdObj是不同的。在创建集合元数据时会先创建一个临时的集合。等临时集合创建好后,会把旧集合的数据和索引拷贝过来,然后重命名这个临时集合。
至此shardCollection的主要流程解释完成。
- 点赞
- 收藏
- 关注作者
评论(0)