分片的策略
Last updated
Was this helpful?
Last updated
Was this helpful?
以下内容来自“运维那点事”, 原文链接:
MongoDB的分片策略有两种:哈希分片和范围分片
对于基于范围的分片,MongoDB按照片键的范围把数据分成不同部分。
如上图,假设有一个数字的片键:想象一个从负无穷到正无穷的直线,每一个片键的值都在直线上画了一个点。MongoDB把这条直线划分为更短的不重叠的片段,并称之为数据块,每个数据块包含了片键在一定范围内的数据。在使用片键做范围划分的系统中,拥有”相近”片键的文档很可能存储在同一个数据块中,因此也会存储在同一个分片中。
注:当你选择的片键是单调递增的,类似MySQL的自增主键, 假如你插入了200个文档,到第100个文档由于达到阈值,文档分片了,但是你前面这100个文档都是在同一台机器,同一个分片上进行写入,所以会造成单点数据吞吐量过大。
哈希分片的原理是将一个字段指定为哈希索引,再把该索引指定为分片键,从而实现数据的分片。
基于哈希片键最大的好处就是保证数据在各个节点分布基本均匀。对于基于哈希的分片,MongoDB计算一个字段的哈希值,并用这个哈希值来创建数据块。在使用基于哈希分片的系统中,拥有”相近”片键的文档很可能不会存储在同一个数据块中,因此数据的分离性更好一些。
注:
在使用散列索引当作分片键时,MongoDB会自动计算哈希值。
在把字段设为哈希索引时,该字段的类型最好不要为浮点数,因为浮点数在MongoDB中会转化成64位整数,容易造成哈希碰撞(2.2, 2.3的哈希值是一样的)
基于范围的分片方式提供了更高效的范围查询,给定一个片键的范围,分发路由可以很简单地确定哪个数据块存储了请求需要的数据,并将请求转发到相应的分片中。不过,基于范围的分片会导致数据在不同分片上的不均衡。有时候,带来的消极作用会大于查询性能的积极作用。比如,如果片键所在的字段是线性增长的,一定时间内的所有请求都会落到某个固定的数据块中,最终导致分布在同一个分片中。在这种情况下,一小部分分片承载了集群大部分的数据,系统并不能很好地进行扩展。
与此相比,基于哈希的分片方式以范围查询性能的损失为代价,保证了集群中数据的均衡。哈希值的随机性使数据随机分布在每个数据块中,因此也随机分布在不同分片中。但是也正由于随机性,一个范围查询很难确定应该请求哪些分片,通常为了返回需要的结果,需要请求所有分片。
详情参见:
详情参见: