`

【转】如何选择MongoDB的分片字段(Shard Key)

 
阅读更多

将存储在MongoDB数据库中的Collection进行分片需要选定分片KeyShard key),对于分片Key的选定直接决定了集群中数据分布是否均衡、集群性能是否合理。那么我们究竟该选择什么样的字段来作为分片Key呢?有如下几个需要考虑点。

以下述记录日志的Document为例:

{

   server : "ny153.example.com" ,

   application : "apache" ,

   time : "2011-01-02T21:21:56.249Z" ,

   level : "ERROR" ,

   msg : "something is broken"

}

基数

Mongodb中一个被分片的Collection的所有数据都存放在众多的Chunk中。一个Chunk存放分片字段的一个区间范围的数据。选择一个好的分片字段非常重要,否则就会遭遇到不能被拆分的大Chunk

用上述的日志为例,如果选择{server:1}来作为一个分片Key的话,一个server上的所有数据都是在同一个Chunk中,很容易想到一个Server上的日志数据会超过200MB(默认Chunk大小)。如果分片Key{server:1,time:1},那么能够将一个Server上的日志信息进行分片,直至毫秒级别,绝对不会存在不可被拆分的Chunk

Chunk的规模维持在一个合理的大小是非常重要的,只有这样数据才能均匀分布,并且移动Chunk的代价也不会过大。

写操作可扩展

使用分片的一个主要原因之一是分散写操作。为了实现这个目标,尽可能的将写操作分散到多个Chunk就尤为重要了。

用上述的日志实例,选择{time1}来作为分片key将导致所有的写操作都会落在最新的一个Chunk上去,这样就形成了一个热点区域。如果选择{server:1,application:1,time:1}来作为分片Key的话,那么每一个Server上的应用的日志信息将会写在不同的地方,如果有100Server和应用对,有10Server,那么每一台Server将会分担1/10的写操作。

查询隔离

另外一个需要考虑的是任何一个查询操作将会由多少个分片来来提供服务。最理想的情况是,一个查询操作直接从Mongos进程路由到一个Mongodb上去,并且这个Mongodb拥有该次查询的全部数据。因此,如果你知道最为通用的查询操作的都以server作为一个查询条件的话,以Server作为一个起始的分片Key会使整个集群更加高效。

任何一个查询都能执行,不管使用什么来作为分片Key,但是,如果Mongos进程不知道是哪一个Mongodb的分片拥有要查询的数据的话,Mongos将会让所有的Mongod分片去执行查询操作,再将结果信息汇总起来返回。显而易见,这回增加服务器的响应时间,会增加网络成本,也会无谓的增加了Load

排序

在需要调用sort()来查询排序后的结果的时候,以分片Key的最左边的字段为依据,Mongos可以按照预先排序的结果来查询最少的分片,并且将结果信息返回给调用者。这样会花最少的时间和资源代价。

相反,如果在利用sort()来排序的时候,排序所依据的字段不是最左侧(起始)的分片Key,那么Mongos将不得不并行的将查询请求传递给每一个分片,然后将各个分片返回的结果合并之后再返回请求方。这个会增加Mongos的额外的负担。

可靠性

选择分片Key的一个非常重要因素是万一某一个分片彻底不可访问了,受到影响的Chunk有多大(即使是用貌似可以信赖的Replica Set)。

假定,有一个类似于Twiter的系统,Comment记录类似如下形式:

{

   _id: ObjectId("4d084f78a4c8707815a601d7"),

   user_id : 42 ,

   time : "2011-01-02T21:21:56.249Z" ,

   comment : "I am happily using MongoDB",

}

由于这个系统对写操作非常敏感,所以需要将写操作扁平化的分布到所有的Server上去,这个时候就需要用id或者user_id来作为分片Key了。使用Id作为分片Key有最大粒度的扁平化,但是在一个分片宕机的情况下,会影响几乎所有的用户(一些数据丢失了)。如果使用User_id作为分片Key,只有极少比率的用户会收到影响(在存在5个分片的时候,20%的用户受影响),但是这些用户会再也不会看到他们的数据了。

索引优化

正如在别的章节中提到索引的一样,如果只有一部分的索引被读或者更新的话,通常会有更好的性能,因为“活跃”的部分在大多数时间内能驻留在内存中。本文上述的所描述的选择分片Key的方法都是为了最终数据能够均匀的分布,与此同时,每一个Mongod的索引信息也被均匀分布了。相反,使用时间戳作为分片key的起始字段会有利于将常用索引限定在较小的一部分。

假定有一个图片存储系统,图片记录类似于如下形式:

{

   _id: ObjectId("4d084f78a4c8707815a601d7"),

   user_id : 42 ,

   title: "sunset at the beach",

   upload_time : "2011-01-02T21:21:56.249Z" ,

   data: ...,

}

你也能构造一个客户id,让它包括图片上传时间对应的月度信息和一个唯一标志符(ObjectID,数据的MD5等)。记录看起来就像下面这个样子的:

 {

   _id: "2011-01-02_4d084f78a4c8707815a601d7",

   user_id : 42 ,

   title: "sunset at the beach",

   upload_time : "2011-01-02T21:21:56.249Z" ,

   data: ...,

}

客户id作为分片key,并且这个id也被用于去访问这个Document。即能将数据均衡的分布在各个节点上,也减少了大多数查询所使用的索引比例。

更进一步来讲:

在每一个月份的开始,在开最初的一段时间内只有一个Server来存取数据,随着数据量的增长,负载均衡器(balancer)就开始进行分裂和迁移数据块了。为了避免潜在的低效率和迁移数据,预先创建分片范围区间是明智之举。(如果有5Sever则分5个区间)

可以继续改进,可以把User_ID包含到图片的id中来。这样的话会让一个用户的所有Document都在一个分片上。比如用“2011-01-02_42_4d084f78a4c8707815a601d7”作为图片的id

GridFS

根据需求的不同,GridFS有几种不同的分片方法。基于预先存在的索引是惯用的分片办法:

1)“files”集合(Collection)不会分片,所有的文件记录都会位于一个分片上,高度推荐使该分片保持高度灵活(至少使用由3个节点构成的replica set)。

2)“chunks”集合(Collection)应该被分片,并且用索引”files_id:1”。已经存在的由MongoDB的驱动来创建的“files_id,n”索引不能用作分片Key(这个是一个分片约束,后续会被修复),所以不得不创建一个独立的”files_id”索引。使用“files_id”作为分片Key的原因是一个特定的文件的所有Chunks都是在相同的分片上,非常安全并且允许运行“filemd5”命令(要求特定的驱动)。

运行如下命令:

> db.fs.chunks.ensureIndex({files_id: 1});

> db.runCommand({ shardcollection : "test.fs.chunks", key : { files_id : 1 }})

{ "collectionsharded" : "test.fs.chunks", "ok" : 1 }

由于默认的files_id是一个ObjectIdfiles_id将会升序增长,因此,GridFS的全部Chunks都会被从一个单点分片上存取。如果写的负载比较高,就需要使用其他的分片Key了,或者使用其它的值(_id)来作为分片Key了。

 

选择分片Key的需要考虑的因素具有一定的对立性,不可能样样的具备,在实际使用过程中还是需要根据需求的不同来进行权衡,适当放弃一些。没有万能的普适分片办法,需求才是王道。

 

转自 http://blog.csdn.net/zhangzhaokun/article/details/6324389

分享到:
评论

相关推荐

    mongodb中文API及分布式分片实例详解

    在本篇中,我们将深入探讨MongoDB的中文API以及如何实施分布式分片,旨在帮助开发者更好地理解和应用这一强大的数据库技术。 一、MongoDB中文API详解 1. 连接与断开:MongoDB的中文API提供了连接数据库的方法,如`...

    Mongodb shard 简介

    要实现分片功能,我们需要指定集合的分片 key(相当于 Oracle 分区字段),这个分片 key 通常需要创建一个索引。分片 key 可以由一个或多个字段构成。 Chunks Chunk 是一个集合中的一段连续数据。当一个 chunk ...

    MongoDB分片实例.pdf

    它根据预设的片键(Shard Key)将数据分配到不同的分片上,同时从config服务器获取分片信息。 - **mongod(数据库实例)**:存储数据的基本单位,可以是不分片的普通数据库实例,也可以是分片集群的一部分。 - **...

    原创Linux下Mongodb的分布式分片群集(sharding cluster)配置

    1. 选择一个集合进行分片,通常根据数据的自然分布选择分片键(shard key)。例如,如果数据有地理分布,可以使用地理位置字段作为分片键: ``` use myDatabase db.myCollection.enableSharding() sh....

    配置mongodb分片群集1

    分片键的选择对性能有很大影响,通常选择具有均匀分布且不会频繁改变的字段作为分片键,以确保数据均衡分布。一旦配置完成,整个系统就能动态地调整数据分布,随着数据量的增长,可以根据需要添加更多的Shard Server...

    配置mongodb分片群集(sharding cluster)

    2. **分片键(Shard Key)**:确定数据在分片集群中分布的依据,它是文档中的一个字段,用于决定文档应存储在哪个分片上。选择合适的分片键对于优化数据分布和查询性能至关重要。 3. **路由进程(Mongos)**:作为...

    MongoDB分片测试

    启用集合分片使用`sh.shardCollection(databaseName.collectionName, shardKey)`命令,例如`sh.shardCollection("testdb.myColl", {"myField": 1})`,其中`myField`是分片键,`1`表示升序分布。 分片测试的目的是...

    MongoDB分片详解

    MongoDB的分片技术是为了解决大数据存储和高负载问题而设计的一种扩展策略。它允许数据分散在多个机器上,以实现水平扩展,确保应用性能不受数据增长的影响。分片不仅能增加存储容量,还能通过负载均衡提升读写速度...

    MongoDB分片集群部署详解

    在分片集群中,数据分片通常是基于特定的分片键,这可以是文档中的一个字段,用于决定数据如何在分片间分布。分片策略有哈希分片、范围分片和复合分片。选择合适的分片键和策略对于优化查询性能和平衡数据分布至关...

    Scaling MongoDB.pdf

    数据分割的过程通常基于一个特定字段,即“shard key”(分片键),这个字段的选择对整个系统的性能至关重要。 **2. 分布数据** 数据分布是指将chunks分配到不同的物理服务器上的过程。为了确保数据的均衡分布,...

    MongoDB分片在部署与维护管理中常见的事项总结大全

    它根据分片键(shard key)将请求路由到合适的分片,并将结果合并返回给客户端,使得分片对应用程序透明。 2. **Config Server(配置服务器)**:存储分片集群的元数据,如分片信息、chunk的分布等。它们通常以复制...

    MongoDB简介与实践.pdf

    - 分区键(PartitionKey)在MongoDB中称为分片键(ShardKey) 10. MongoDB文档示例: MongoDB的文档是一种以BSON格式存储的数据结构,类似于JSON。文档包含一个唯一的_id字段,可以通过ObjectId进行索引,字段可以...

    mongdb分片教程

    - **分片键(Shard Key)**:用于确定文档如何分布在各个分片上的字段或字段组合。选择合适的分片键对于数据分布和查询性能至关重要。 #### 二、MongoDB分片模型图解析 - **分片模型图**:展示了MongoDB如何通过分...

    2012 mongodb 最新的sharding配置

    MongoDB 是一个流行的开源文档型数据库系统,它支持横向扩展,通过分片(Sharding)技术来处理大规模的数据存储和查询。在2012年的版本中,MongoDB 的分片配置是分布式数据库设置的关键步骤,旨在提高系统的可扩展性...

    mong分片配置.zip

    5. 添加分片:通过 Mongos 将新的分片添加到集群中,并指定分片的键(Shard Key),这是决定数据如何分配到分片的字段。 6. 分配数据:根据需求,手动或自动将已有数据分片。 7. 监控与维护:持续监控分片集群的...

    mongodb分片技术_动力节点Java学院整理

    MongoDB的分片机制基于“片键”(Shard Key)来决定数据如何分布。片键是用于确定数据如何在片之间分割的字段。数据会根据片键的值自动分配到不同的片上。例如,如果片键是用户ID,那么数据会根据用户ID的大小进行...

    Scaling MongoDB

    系统自动决定数据存储在哪个分片上,这是通过分片键(Shard Key)来实现的。选择合适的分片键对于维护数据平衡和系统性能至关重要。分片键的选择通常需要考虑数据的分布特性,避免数据倾斜,确保分片能够均匀分配...

    MongoDB大型部署详细方案.zip_MongoDB_mongo

    2. 配置服务器(Config Server):配置服务器是分片集群的关键组件,它们存储了所有分片和路由信息,包括数据的分片键(Shard Key)以及数据所在的分片位置。每台配置服务器都保存了元数据的完整副本,确保了元数据...

    MongoDB集群高可用部署方案.docx

    选择合适的分片键(shard key)至关重要,它是基于文档的某个字段进行数据分布的依据。shard key一旦选定,就不能更改,其选择直接影响集群的性能、扩展性和数据分布均衡。对于非空集合分片,需要预先建立基于shard ...

    深入浅出MongoDB应用实战集群及系统架构

    - **分片键(Shard Key)**:用于决定文档存储位置的字段。 #### MongoDB集群搭建步骤 1. **安装MongoDB** - 在所有服务器上安装MongoDB软件。 - 配置必要的环境变量。 2. **配置副本集** - 在每台服务器上...

Global site tag (gtag.js) - Google Analytics