mongodb 分片键
当你觉得生活对你不公时,秤秤体重,照照镜子,你会觉得一切又合乎情理。
什么是分片键?
分片键(Shard Key) 就是文档里面的一个字段,但是这个字段不是普通的字段。
分片键的作用是数据分区的前提, 从而实现数据分发到不同服务器上,减轻服务器的负担。也就是说,分片键决定了集合内的文档如何在集群的多个分片间的分布状况。
分片键的要求:
- 它必须在所有文档中都出现。
- 它必须是集合的一个索引,可以是单索引或复合索引的前缀索引,不能是多索引、文本索引或地理空间位置索引。
- MongoDB 4.2 之前的版本,文档的分片键字段值不可变。MongoDB 4.2 版本开始,除非分片键字段是不可变的 _id 字段,否则您可以更新文档的分片键值。MongoDB 5.0 版本开始,实现了实时重新分片(live resharding),可以实现分片键的完全重新选择。
- 它的大小不能超过 512 字节。
如何选分片键?
选择合适的片键对 sharding 效率影响很大,主要基于如下四个因素:
1、取值基数:取值基数建议尽可能大,如果用小基数的片键,因为备选值有限,那么块的总数量就有限,随着数据增多,块的大小会越来越大,导致水平扩展时移动块会非常困难。 例如:选择年龄做一个基数,范围最多只有100个,随着数据量增多,同一个值分布过多时,导致 chunck 的增长超出 chuncksize 的范围,引起 jumbo chunk,从而无法迁移,导致数据分布不均匀,性能瓶颈。
2、取值分布:取值分布建议尽量均匀,分布不均匀的片键会造成某些块的数据量非常大,同样有上面数据分布不均匀,性能瓶颈的问题。
3、查询带分片:查询时建议带上分片,使用分片键进行条件查询时,mongos 可以直接定位到具体分片,否则 mongos 需要将查询分发到所有分片,再等待响应返回。
4、避免单调递增或递减:单调递增的 sharding key,数据文件挪动小,但写入会集中,导致最后一篇的数据量持续增大,不断发生迁移,递减同理。
分片策略:
1、基于范围的分片
MongoDB 按照分片键(Shard Key)的值的范围将数据拆分为不同的块(Chunk),每个块包含了一段范围内的数据。当分片键的基数大、频率低且值非单调变更时,范围分片更高效。
优点: Mongos 可以快速定位请求需要的数据,并将请求转发到相应的 Shard 节点中。
缺点: 可能导致数据在 Shard 节点上分布不均衡,容易造成读写热点,且不具备写分散性。
适用场景:分片键的值不是单调递增或单调递减、分片键的值基数大且重复的频率低、需要范围查询等业务场景
2、基于 Hash 值的分片
MongoDB 计算单个字段的哈希值作为索引值,并以哈希值的范围将数据拆分为不同的块(Chunk)。
优点:可以将数据更加均衡地分布在各 Shard 节点中,具备写分散性。
缺点:不适合进行范围查询,进行范围查询时,需要将读请求分发到所有的 Shard 节点。
适用场景:分片键的值存在单调递增或递减、片键的值基数大且重复的频率低、需要写入的数据随机分发、数据读取随机性较大等业务场景。
注:除了上述两种分片策略,您还可以配置复合片键 ,例如由一个低基数的键和一个单调递增的键组成。