MongoDB 对同一数据库中的相关集合进行分片

MongoDB Sharding for related collections in same Database

我正在为分布在不同国家和城市的地理分布式应用程序设计架构。还有相关的合集比如-

商店(分布在各个国家和城市) 商店的 15 天交易(其余时间用于历史商店) 等等

是否可以保证商店和商店的交易在同一个分片中? 目前在交易集合中,假设我只存储商店的唯一 _id 作为参考。

假设我使用 {region, country, city, shop_id} 等键对 Shop 集合进行分片。 我是否必须为交易 table 存储相同的 columns/attributes - 即地区,国家,城市, shop_id 而不仅仅是 shop_id 然后选择一个分片键 - {region, country, city, shop_id, tx_id} 以确保它与 Shop 集合放在同一个分片中?

换句话说,如果 'child' 集合的记录与 'parent' 集合的记录在逻辑上相关,那么我们应用于 'parent' 集合的整个分片键必须成为 'child' 的分片键的一部分以确保它们位于同一个分片上?

感谢和问候, Archanaa 熊猫

这是我从另一个论坛找到的 https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!topic/mongodb-user/1cwyfqt6UTo

快速总结 -

  • 相关的合集在同一个区域比在同一个服务器更重要
  • 要实现这一点,您必须为至少具有部分相同属性(例如国家/地区)的两个集合选择分片键
  • 要为国家/地区的标签感知分片指定分片范围,我们可以这样设置范围 - sh.addTagRange("commerce.shops", { "country" : "IN" }, { "country" :"IN" }, "APAC") sh.addTagRange("commerce.shops", { "country" : "SG" }, { "country" :"SG" }, "APAC") 并分配这样的标签"APAC" 该区域的特定分片。

这是我的做法。虽然每个国家都有一个或多个分片的有效用例,但通常您希望根据区域进行地理分布。通常的那些——EMEA、APAC 和 NCSA——应该足够了,我将在我的例子中使用它。作为旁注:您可能希望将 EMEA 拆分为 EME(欧洲数据中心)和 A(我在南部非洲的数据中心有很好的经验),因为有时进出非洲的连接......不是最佳的。

至于碎片,我假设三个碎片分别命名为 shard0 (EMEA)、shard1 (APAC) 和 shard3 (NCSA)。

正如您所发现的,将每个区域的数据放在单个分片上(这不会非常可扩展)并不太重要,但在具有相同标签的分片上。我强烈建议将具有相同标签的所有分片及其前端托管在同一个数据中心:内部流量往往是免费的,内部带宽通常比(或至少可以升级到更高)高得多外部带宽。

  1. 定义您的区域和应该保存这些区域数据的分片。
  2. 设置您的配置服务器。出于元数据可用性的原因,我会为每个区域设置一个配置服务器。因此,即使数据中心出现故障,您也可以使用其他两个数据中心启动一个额外的配置服务器。
  3. 设置您的分片。由于速度对您来说似乎是个问题:使用 SSD。它们的速度如此之快,以至于它们可以轻松地为您保存多个碎片,因为旋转磁盘通常会成为限制因素。

  4. 标记碎片:

    sh.addShardTag("shard0", "EMEA")
    sh.addShardTag("shard1", "APAC")
    sh.addShardTag("shard2", "NCSA")
    
  5. 添加标签范围。如果您有每个商店的区域,则无需按国家/地区进行。只需按地区标记:

    sh.addTagRange("commerce.shops",{"region":"EMEA"},{"region":"EMEA"},"EMEA")
    sh.addTagRange("commerce.shops",{"region":"APAC"},{"region":"APAC"},"APAC")
    sh.addTagRange("commerce.shops",{"region":"NCSA"}, {"region":"NCSA"},"NCSA") 
    

    我不分配国家代码的原因是您必须将每个国家代码分配给一个标签。既然您已经拥有该区域,为什么不用它来让您的生活更轻松呢?

  6. 作为分片键,我会使用区域的复合键以及您认为合适的任何内容。请注意,您不应将 ObjectId 用作分片键的另一组成部分,因为它是单调递增的,如果每个区域有多个分片,这将导致问题。假设您的 ShopId 是分片键的另一部分,它是一个 ObjectId,有一个解决方法:使用 a hashed shard key.

    sh.shardCollection("commerce.shops",{"region":1,"shopId":"hashed"})
    

    这样,所有文档都将分发到负责各自区域的分片,同时仍然允许在它们之间分发块。

hth.