设为首页 收藏本站
查看: 658|回复: 0

[经验分享] [mongodb翻译]选择合适的shard key

[复制链接]

尚未签到

发表于 2015-7-7 11:14:57 | 显示全部楼层 |阅读模式
  为一个集合(collection)选择合适的shard key非常重要。如果这个集合非常庞大,那么将来再来修改shard key将会很困难。如有任何疑问请到论坛或者IRC寻求帮助。
  
  示例文档



view plain

  • {  
  • server : "ny153.example.com" ,  
  • application : "apache" ,  
  • time : "2011-01-02T21:21:56.249Z" ,  
  • level : "ERROR" ,  
  • msg : "something is broken"  
  • }  
  
基数(cardinality)
  一个集合中的所有数据会被分裂为多个数据块(chunk),一个数据块包含了某个范围shard key的数据。请选择合适的shard key,否则你将会得到很大的不能分裂的数据块。
  使用上面的日志例子,如果你选择了:



view plain

  • {server:1}  
  
作为shard key,那么所有关于某个server的数据会存在一个数据块中,你可以很容易想到一个server的数据会超过64MB(默认数据块大小)。如果shard key是:



view plain

  • {server:1,time:1}  
  
你可以将单个服务器的数据分裂到毫秒级。只要你的单个服务器不会有200MB/S,就不会有不能分裂的数据块。
  保持数据块在一个合适大小是很重要的,这样数据就可以在集群中均衡分布并且移动一个数据块代价也不会太大。
  
  水平写
  使用分片的一个主要原因就是分发写操作。为了达到这个目的,写操作应当尽可能的分散到不同的数据块。
  再次使用前面的例子,选择:



view plain

  • { time : 1 }  
  
作为shard key,会导致所有的写操作都集中到最新的数据块中。如果shard key选择:



view plain

  • {server:1,application:1,time:1}  
  
那么每个服务器:应用映射都会被写到不同的地方。如果这里有100种服务器:应用映射,和10台服务器,那么每台服务器将会分配约1/10的写操作。
  需要注意的是,由于ObjectId中很重要的一部分是基于时间生成的,使用ObjectId作为shard key等同于直接使用时间值。
  
  查询隔离
  另外一个考虑就是任何一个查询需要分发到多少个shard。理想情况下,一个查询操作经mongos直接分发到拥有期望数据的mongod。如果你知道大部分的查询使用了那些条件,那么使用这些条件属性作为shard key可以提高很多效率。
  即使查询条件中没有包含shard key,查询依然可以工作。由于mongos不知道哪个shard拥有期望的数据,mongos会将这个请求顺序分发到所有的shard中,这会增加响应时间和网络数据流量及服务器负载。
  
  排序
  如果查询中包含了排序请求,这个查询请求会同以前没有排序要求时一样分发到需要的shard中。每一个shard执行查询然后在本地做排序(如果有 索引的话会使用索引)。mongos会合并从shard返回的已经排序好的结果,然后返回合并后的数据给客户端。这样的话,mongos只需要做少量的工 作和很少的RAM。

  可靠性
  分片的一个重要方面就是如果整个shard不能访问了(即使使用了可靠的复制组),这将会对整个系统带来多大的影响。
  例如你有一个类似于twitter的系统,评论记录类似于:



view plain

  • {  
  • _id: ObjectId("4d084f78a4c8707815a601d7"),  
  • user_id : 42 ,  
  • time : "2011-01-02T21:21:56.249Z" ,  
  • comment : "I am happily using MongoDB",  
  • }  
  
由于系统对写操作是非常敏感的,如果你希望将写操作分散到各个服务器中,你需要使用"_id"或者"user_id"作为shard key。"_id"可以给你较好的颗粒度和写扩散性。但是一旦某个shard宕机了,它将会影响到几乎所有的用户(有些数据丢失了)。如果你使 用"user_id"作为shard key,此时一小部分用户会受到影响(比如在5个shard组成的集群中,这个百分比是20%),即使这些用户再也看不到他们的任何数据了。
  
  索引最佳化
  正如前面章节关于索引的描述,通常经常对一部分索引做读/更新会带来较好的性能表现,这是因为这“活跃”的部分可以大多数时间都驻留在RAM。前面 介绍的shard key虽然可以将写操作分散到各个shard中,但是他们还是属于每个mongod的索引的。作为替代,将时间戳分解为某种形式并作为shard key的前缀可以带来一些好处,这样可以减小经常访问的索引大小。
  例如你有一个图片存储系统,图片记录类似于:



view plain

  • {  
  • _id: ObjectId("4d084f78a4c8707815a601d7"),  
  • user_id : 42 ,  
  • title: "sunset at the beach",  
  • upload_time : "2011-01-02T21:21:56.249Z" ,  
  • data: ...,  
  • }  
  
你可以定制一个包含了上传时间的月份和唯一的标示符(如ObjectId,数据的md5值等)的_id来替代默认的_id,新的记录类似于:



view plain

  • {  
  • _id: "2011-01_4d084f78a4c8707815a601d7",  
  • user_id : 42 ,  
  • title: "sunset at the beach",  
  • upload_time : "2011-01-02T21:21:56.249Z" ,  
  • data: ...,  
  • }  
  
使用它作为shard key,同时也是访问一个文档使用的_id.它可以很好的将写操作分散到所有shard中。并且它减小了大部分查询需要访问的索引的大小。
  进一步注释:

  • 在每个月的开始,只有一台shard被访问知道均衡器开始分裂数据块。为了避免这种潜在的低性能和数据迁移,建议在时间前面增加了一个范围值(比如5或者更大的范围值如果你有5台服务器)。
  • 更进一步的改善,你可以将用户名(user id)纳入到图片id中,这样可以保持同一个用户的文档都存储到同一个shard中,例如:"2011-01_42_4d084f78a4c8707815a601d7"
  
  GirdFS
  根据不同的需要,这里有多种不同的方法可以对GridFS进行分片。一种基于已经存在的索引的分片方法是:

  • "files"集合不做分片。所有的文件记录都将存储在一个shard中,强烈建议保证该shard非常可靠(使用至少3节点的复制组)。
  • "chunks" 集合应当使用索引"files_id:1"进行分片。由驱动创建的已经存在的"files_id,n"索引不能被使用在"files_id"上面进行分片 (这是一个限制,将来会被fix)。所以你需要单独为"files_id"创建一个索引。使用"files_id"进行分片开始保证某个文件存储到同一个 shard中,这样"filemd5"命令就可以工作了。运行命令:


    view plain

    • > 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默认使用ObjectId,因此files_id是递增的,所有新的GridFS数据块会被送往同一个shard。如果你的写负载太大以至于单台服务器无法应付,你可能需要考虑使用其他的shard key或者使用其他的值作为file的_id.

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-84072-1-1.html 上篇帖子: MongoDB源码概述——使用日志提升单机数据可靠性 下篇帖子: mongoDB oplog的说明及应用
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表