zoukankan      html  css  js  c++  java
  • MongoDB 分片键分类与数据分发

    In sharded clusters, if you do not use the _id field as the shard key, then your application must ensure the uniqueness of the values in the _id field to prevent errors.

    This is most-often done by using a standard auto-generated ObjectId.

    在分片中,也要保证object id的唯一性

    整理自:

    https://www.cnblogs.com/chenmh/p/8954584.html

    https://cloud.tencent.com/developer/article/1451897

    《MongoDB权威指南》

    MongoDB拆分数据常用的数据分发方式有三种:

    升序片键

    随机分发片键

    基于位置片键

    一、升序片键

    1.1 什么是升序片键

    升序片键通常有点类似于date字段或者时objectId,是一种随着时间稳定增长的字段。

    1.2 升序片键数据插入表现

    升序片键在数据插入会带来一些属性,通常是不良属性

    1、最大快现象

    假设要建立一个新文档,它会位于哪个块?答案是范围为objectId("5115aa552cascsa222")到

    $maxkey的块。这个块叫做最大快。因为此块包含$maxkey。

    所有的写都会被路由到一个分片中。该块是唯一一个不断增长和拆分的块,因为他是唯一一个能够接收到插入请求的块。

    随着新数据的不断插入,该最大块会不断拆分处新的小块。

    2、分片内的数据块不均匀

    这种模式经常导致MongoDB的数据均匀处理变得更为困难,因为所有的新块都是由同一分片创建。因此,

    MongoDB必须不断将一些块移入其他分片,而不能像在一个比较均匀的分发系统中那样,只需纠正那些

    比较小的不均衡就好了。

    二、随机分发的片键

    2.1 什么是随机分发片键

    随即分发的键可以是用户名、邮件地址、UDID(唯一设备标识符)、MD5散列值,或者是数据集中其他一些

    没有规律的键。

    2.2 随即分发片键数据插入表现

    1、写入数据是随机分发,各个片键增长速度应大致相同,减少了需要进行迁移的次数

    2、随即分发唯一弊端在于

    MongoDB在随机访问超出RAM大小的数据失效率不高。然而,如果拥有足够多的RAM或者是并不介意系统

    性能的话,使用随机片键在集群上分配负载是非常好的。

    三、基于位置的片键

    3.1 什么是基于位置的片键

    基于位置的片键可以是用户的IP、经纬度、或者是地址。

    位置片键不必与实际的物理位置字段相关:这里的位置比较抽象,数据会依据这个位置进行分组。无论

    如何,所有与该键值比较接近的文档都会被保存在同一范围的块中。这样可以比较方便的将数据与相应的

    用户,以及相关联的数据保存在一起。

    3.2 基于位置的片键数据插入表现

    1、使用tag将特定范围的块出现在特定的分片中。

    比如:IP段,让“56.*.*.*"(美国邮政署的IP段)出现在shard0000,让"17.*.*.*"(苹果公司的IP段)出现在

    shard0000或者shard0002上。

    >sh.addShardTag("shard0000","USPS")

    >sh.addShardTag("shard0000","Apple")

    >sh.addShardTag("shard0002","Apple")

    四、片键策略

    针对不同类型应用程序的几种片键选项

    4.1 散列片键

    1、散列片键特性

    优点:

    如果追求数据加载速度的极致,那么散列片键(Hashed Shard Key)是最佳选择。

    散列片键可使其他任何键随机分发,因此,如果打算在大量查询中使用升序键,但同时又希望写入

    数据随机分发的话,散列片键是个非常好的选择。

    弊端:

    无法使用散列片键做指定目标的范围查询。如果无需做范围查询,那么散列片键就非常适合。

    2、创建一个散列片键

    1)数据库启用分片

    >sh.enableSharding("app")

    2)在已经存在集合上面使用散列片键

    创建散列索引

    >sh.users.ensureIndex({"username":"hashed"})

    然后对集合分片

    >sh.shardCollection("app.users",{"username":"hashed"})

    3)在不存在的集合上面使用散列片键

    语法同上,但是有如下注意点

    MongoDB假设我们希望对数据块进行均衡分发,所以他会立即创建一些空的块,并将这些块分发在集群

    中。

    3、散列分片的局限

    1)不能使用unique选项

    2)与其他分片键一样,不能使用数组字段

    3)浮点型的值会被取证,然后才进行散列,所以1和1.999会得到形同的散列值

    4.2 Ranged Sharding 范围片键

    通过分片键的值来将数据分成不同的范围。它可以提供比较快的范围查询,但是当分片键选择不好的时候,也会降低读写性能 。 如果没有配置Hashed Sharding或者zones(https://docs.mongodb.com/manual/core/zone-sharding/#zone-sharding)它是默认的分片键方法。

    sh.shardCollection( "database.collection", { <shard key> } )

    大致分布见下图:

    4.3zones sharding(列表分区)

    The following image illustrates a sharded cluster with three shards and two zones. The A zone represents a range with a lower boundary of 1 and an upper bound of 10. The B zone represents a range with a lower boundary of 10 and an upper boundary of 20. Shards Alpha and Beta have the A zone. Shard Beta also has the B zone. Shard Charlie has no zones associated with it. The cluster is in a steady state and no chunks violate any of the zones.

    For example, given a shard key { a : 1, b : 2, c : 3 }, creating or updating a zone to cover values of b requires including a as the prefix. Creating or updating a zone to covers values of c requires including a and b as the prefix. 创建shard tag:

    sh.addShardTag("shard0000", "NYC")sh.addShardTag("shard0001", "NYC")sh.addShardTag("shard0002", "SFO")sh.addShardTag("shard0002", "NRT")

    创建zone rang:

    sh.addTagRange("records.users", { zipcode: "10001" }, { zipcode: "10281" }, "NYC")sh.addTagRange("records.users", { zipcode: "11201" }, { zipcode: "11240" }, "NYC")sh.addTagRange("records.users", { zipcode: "94102" }, { zipcode: "94135" }, "SFO")

    参考:https://docs.mongodb.com/manual/tutorial/manage-shard-zone/

    与hashed shard key一起使用时,zone的范围一般要覆盖minKey和maxKey才可以。 参考:https://docs.mongodb.com/manual/core/zone-sharding/#zone-sharding

    比如对于一些日志非查询文档,可以通过标签将其只插入到某个分片中。例如

    sh.addTagRange("test.log",{ "_id" : { "$minKey" : 1 }  }, { "_id" : { "$maxKey" : 1 } },"tag_rs-a");

    可以在config库中的tag文档中查看设置的标签信息。

    use config
    
    db.tags.find();

    4.4 组合片键

    数据库中没有比较合适的片键供选择,或者是打算使用的片键基数太小(即变化少如星期只有7天可变化),可以选另一个字段使用组合片键,甚至可以添加冗余字段来组合。一般是粗粒度+细粒度进行组合。

    组合片键的创建,对GridFS的chunks集合使用files_id和n组合分片。

    组合分片是比较好的一种分片的选择,好的组合分片可以同时解决热点和随机读IO问题。例

      1)数据库启用分片

      sh.enableSharding("test")


    2)集合设置分片键(新建分片情况)
    sh.shardCollection("test.bbbb",{"username":1,"_id":1});

    3)查分片信息
    sh.status()
  • 相关阅读:
    最长公共子序列问题LCS
    [LuoguP2900] [USACO08MAR]土地征用(Land Acquisition)
    [LuoguP3195] [HNOI2008]玩具装箱TOY
    $Yeasion$的码风修改历程
    点分治模板
    Poj2919 Crane
    Poj2010 Moo University
    Kuhn-Munkres算法
    Uva10791 Minimum Sum LCM
    P1018 乘积最大(高精度加/乘)
  • 原文地址:https://www.cnblogs.com/xibuhaohao/p/11270524.html
Copyright © 2011-2022 走看看