按 ObjectID 分片,是正确的方法吗?
Posted
技术标签:
【中文标题】按 ObjectID 分片,是正确的方法吗?【英文标题】:Sharding by ObjectID, is it the right way? 【发布时间】:2012-02-06 17:28:15 【问题描述】:我就像许多其他人一样正在考虑在 Mongo 中对我的收藏进行分片的正确方法。主要问题是 - 自动分片是如何工作的?
官方文档说——“MongoDB 通过自动分片(分区)架构水平扩展”和“为了对集合进行分区,我们指定了一个分片键模式。”附注“为集合选择正确的分片键很重要”:)。 http://www.mongodb.org/display/DOCS/Sharding+Introduction#ShardingIntroduction-ShardKeys http://www.mongodb.org/display/DOCS/Choosing+a+Shard+Key
现在的问题是 - “这是正确的密钥”(按 ObjectID 分片)?
db.runCommand( shardcollection : "test", key : _id : 1 )
Mongo 内部发生了什么?在这种情况下,Mongo 如何将数据拆分为块?假设我最初有 1000 万条记录和 2 个分片服务器 - 当我想在收集达到 2000 万条记录时再添加 2 个分片服务器时,Mongo 端会发生什么?我在 Mongo 相关资源的任何地方都找不到该级别的详细信息。
考虑到自动生成 _id 的随机性及其结构,
...http://www.mongodb.org/display/DOCS/Object+IDs...
我将按最低有效字节(rtl 顺序)分片,并按 2-3 个字节的值拆分块 - 这将提供一种简单的方法来分片 2^N 个分片服务器 - 2、4、8、..、 256 个分片服务器,每个分片上的负载或多或少均匀,所需配置最少。据我了解,Mongo 仅支持通过明确定义的范围进行分片/分块,并且我的想法行不通。是真的吗?
【问题讨论】:
是的,我正处于新项目的积极研究阶段 - 将审查我的所有问题并在研究完成后接受最适用的问题。 @XtraCoder 您的研究进展如何?这个答案似乎值得接受。 【参考方案1】:使用默认对象 id 作为分片键通常不是一个好主意,因为它具有嵌入的时间戳并且随时间单调增加。如果您进行大量更新以使其以均匀分布的方式接触新旧文档,这可能会很好。但是,如果您的应用程序的插入量很大,这确实是个坏消息,因为您的大部分写入都将转到单个分片。这是因为写入将转到拥有 [nearCurrentTimestamp -> infinity] 块的分片。
每个 mongos 监控写入分片的流量,并使用非常简单的启发式方法来确定块是否变得太大并需要拆分(阈值大小可通过 chunkSize 配置)。
当您向集群添加新分片时,平衡器 (http://www.mongodb.org/display/DOCS/Sharding+Administration#ShardingAdministration-Balancing) 将发现块不平衡,并将开始将块迁移到新分片。
Mongo 支持基于范围的分片,但是,这并不意味着范围是固定的,因为块可以分成更小的范围并随着时间的推移在集群中移动。
【讨论】:
接受这个答案,因为它证实了我所问的“我的想法行不通”(不幸的是):( - 但是我想找到让它工作的方法:) 考虑到散列的分片键,这不再是真的,对吧? 使用默认的_id作为HASHED shard key怎么样? _id 是 mongos 还是 mongod 生成的?【参考方案2】:2.4 版中一个令人兴奋的新功能是支持哈希索引,并且可以用作 Shard Keys。因此,您的主要问题“按 ObjectID 进行分片,是正确的方式吗?”的答案现在可能是肯定的!
更多参考资料在官方文档中:
散列分片密钥
http://docs.mongodb.org/manual/core/sharded-cluster-internals/#hashed-shard-keys
散列索引
http://docs.mongodb.org/manual/core/indexes/#hashed-index
【讨论】:
如果您使用“ObjectId 索引”作为日期字段,我不会使用“哈希索引”,除非您的应用程序确实需要大量写入。 请注意这里的重点“以减少查询隔离为代价” 并参考此link以上是关于按 ObjectID 分片,是正确的方法吗?的主要内容,如果未能解决你的问题,请参考以下文章