在阅读了一些关于mongodb cluters上的分片的资料后,我觉得后期阶段的分片键功能和数据迁移很让人烦恼。假设我们有两个分片来存储英语词典的单词。首字母选择分片键。假设以A-C开头的单词被分配给shard-A;用D-Z开头的单词被分配给shard-B。显然,通过这种方式,Shard-B中的单词数量远远多于Shard-A中的单词数量。结果,一段时间后,一些以D-Z开头的单词将从Shard-B迁移到Shard_A以进行数据平衡。所以,我的困惑是,在Shard-A中出现D-Z的单词与通过分割密钥的规则相矛盾。
请帮助我摆脱困惑。 提前谢谢。
答案 0 :(得分:0)
声明
在Shard-B中以A-C开头的单词与通过分片键的规则相矛盾
不是真的。是的,共享密钥始终是相同的,在您的情况下是单词的第一个字母,但是与每个分片关联的分片键的值不是硬编码的,并且可能在平衡期间发生变化。
所以,如果最初我们有以下图片
+---------+---------+
| Shard 1 | Shard 2 |
+---------+---------+
| A-C | D-Z |
+---------+---------+
并且在一段时间内,Shard 2
中的文档正在成为多数,Balancer
将重新平衡数据,并相应地重新分配共享键值,因此您可能会得到另一张图片:
+---------+---------+
| Shard 1 | Shard 2 |
+---------+---------+
| A-L | M-Z |
+---------+---------+
重点是您不直接查询任何分片,甚至不关心数据的分布方式。您所做的是查询mongos
路由器实例,然后所有工作都由MongoDB完成。此外,在查询时,您甚至可能不知道分片键(尽管您更愿意知道要进行有效的查询)。相反,MongoDB获取您的查询,获取分片键值(如果您的查询中有此类值),找出数据可能的分片,然后仅查询该特定分片。
所以说你要查询“堪萨斯”这个词最初属于Shard 2
。
+-----------+
| config db |
+-----------+
↑ |
get shard for | | Shard 2
shard key "K" | |
| ↓
+--------+ query word "Kansas" +--------+ Shard 2 +------------------+
| client | =====================> | mongos | =========> | mongod - Shard 2 |
+--------+ +--------+ +------------------+
所以在平衡之后你会有另一个流程
+-----------+
| config db |
+-----------+
↑ |
get shard for | | Shard 1
shard key "K" | |
| ↓
+--------+ query word "Kansas" +--------+ Shard 1 +------------------+
| client | =====================> | mongos | =========> | mongod - Shard 1 |
+--------+ +--------+ +------------------+
但无论如何,在你的客户端,你不会注意到任何事情。
答案 1 :(得分:0)
当您choose a shard key确定MongoDB群集如何根据观察值自动分区数据时。
您在字母表中单个字母的分片示例将是一个糟糕的选择,因为:
您可以将分片键粒度限制为一组固定的选项(例如,如果值为大写A-Z,则可能有26种选择)。
具有低基数的分片键确实会导致无法进一步细分的范围(即字典的示例,其中有更多单词以“B”开头而不是“X”)。在MongoDB术语中,分片键范围称为 chunks ;那些无法进一步划分的人将被标记为jumbo chunks。 Jumbo块将继续增长,平衡器不会尝试迁移它们。
除非您的应用程序用例涉及经常按大多数查询中的第一个字母进行搜索,否则此分片键对targeted queries也无效。有针对性的查询效率更高,因为mongos
可能会将范围查询限制为一个或多个分片,而不必向所有分片发送查询(又称scatter-gather
个查询)。
注意:如果将单个字母保存为分片集合中每个文档中的字段,则只能选择“单个字母”作为分片键。
更典型的分片键示例是使用具有高基数(良好唯一性)的字段的值。在字典示例中,您可以使用字典单词作为分片键。
假设您从分片空集合开始,这将在概念上演变如下:
该集合以一个覆盖范围的块开始,该范围具有特殊值“MinKey
.. MaxKey
”(也就是从减号到正无穷大,或全部数据)
随着文档的添加,MongoDB估计已经将多少文档插入到给定的块中,并且一旦块大约有64MB的文档,它将自动split chunks到多个范围。
块范围将反映数据的分布,因此在字典示例中,包括B
在内的值范围将包含更多的块,而不是包括X
的数据范围。例如,与“waffle .. yak”相比,可能会有“bab .. bacon”,“baconer .. badger”等等。
基于migration thresholds,MongoDB平衡器将根据需要定期在分片之间重新分配块。
一个好的分片键将具有固有的写入分配,从而最大限度地减少重新平衡工作。您还必须考虑数据的到达方式。例如,如果您基于英语词典中的单词进行分片并按字典顺序插入单词的定义,那么您最终会将所有写入指向当前值范围内的单个“热分片”。相比之下,如果你有一个自然的单词分布(例如,它们出现在报纸文章中),那么写作会更加分散。
假设以A-C开头的单词被分配给shard-A;用D-Z开头的单词被分配给shard-A。
默认情况下,分片键范围和分片之间没有关联。通常的目标是允许根据需要自动重新分配数据。
可以使用tag aware sharding设置一些分片关联,但通常这是出于非常具体的原因,例如多个数据中心或热/冷数据用例(另请参阅:Four Ways to Optimize Your Cluster With Tag-Aware Sharding)。 / p>