用于改变 SLA 或 SLO 的分层硬件

在本页面

在分片群集中,您可以基于碎片 key创建zones分片数据。您可以将每个 zone 与 cluster 中的一个或多个分片相关联。分片可以与任意数量的 zones 相关联。在平衡的 cluster 中,MongoDB 仅将 zone 覆盖的迁移到与 zone 关联的分片。

本教程使用Zones来基于创建 date route 文档,以分割为支持最近文档的分片,或者为支持归档文档分区的分片。

以下是基于 Service Level Agreement(SLA)或 Service Level Objective(SLO)对数据进行分段的一些 example 用例:

  • 应用程序需要提供对最近插入/更新的文档的 low-latency 访问权限

  • 应用程序需要优先处理 low-latency 访问文档的范围或子集

  • 受益于确保特定范围或数据子集的应用程序存储在服务器上,这些服务器具有适合访问该数据的 SLA 的硬件

下图说明了一个分片 cluster,它使用基于硬件的 zones 来满足数据访问 SLA 或 SLO。

分层 SLA 的分片 cluster architecture 图

脚本

照片共享应用程序需要快速访问过去 6 个月内上传的照片。 application 将每张照片的位置及其元数据存储在data集合下的photoshare数据库中。

以下文档代表单个用户上传的照片:

{
  "_id" : 10003010,
  "creation_date" : ISODate("2012-12-19T06:01:17.171Z"),
  "userid" : 123,
  "photo_location" : "example.net/storage/usr/photo_1.jpg"
}
{
  "_id" : 10003011,
  "creation_date" : ISODate("2013-12-19T06:01:17.171Z"),
  "userid" : 123,
  "photo_location" : "example.net/storage/usr/photo_2.jpg"
}
{
  "_id" : 10003012,
  "creation_date" : ISODate("2016-01-19T06:01:17.171Z"),
  "userid" : 123,
  "photo_location" : "example.net/storage/usr/photo_3.jpg"
}

请注意,过去一年(截至 2016 年 6 月)仅上载了带有_id : 10003012的文档。

碎片 Key

照片集使用{ creation_date : 1 }索引作为分片 key。

每个文档中的creation_date字段允许在创建 date 上创建 zones。

建筑

分片 cluster 部署目前包含三个碎片

分层 SLA 的分片 cluster architecture 图

Zones

application 需要根据其硬件层将每个分片添加到 zone。每个硬件层代表一个特定的硬件配置,旨在满足给定的 SLA 或 SLO。

分层 SLA 的分片 cluster architecture 图

  • 快速等级(“最近”)

    • 这些是性能最快的机器,具有大量 RAM,快速 SSD 磁盘和强大的 CPU。

zone 需要一个范围:

  • { creation_date : ISODate(YYYY-mm-dd)}的下限,其中YYYY-mm-dd指定的 Year,Month 和 Date 在过去 6 个月内。

  • { creation_date : MaxKey }的上限。

  • 档案层(“档案”)

    • 这些机器使用较少的 RAM,较慢的磁盘和更多的基本 CPU。但是,它们每台服务器的存储量更大。

zone 需要一个范围:

  • { creation_date : MinKey }的下限。

  • { creation_date : ISODate(YYYY-mm-dd)}的上限,其中 Year,Month 和 Date 匹配用于recent层下限的值。

注意 MinKeyMaxKey值是保留的特殊值,用于比较。

随着 performance 需求的增加,添加额外的分片并根据其硬件层将它们与相应的 zone 相关联,可以使 cluster 水平扩展。

在基于 time spans 定义 zone 范围时,请权衡 zone 范围的不频繁更新与必须在更新上迁移的数据量的优势。例如,将数据设置为“最近”的限制为 1 年可能包含的数据多于设置 1 个月的限制。虽然在 1 个月的规模上轮换时需要更多迁移,但必须迁移的文档数量低于 1 年规模的轮换量。

写操作

使用 zones 时,如果插入或更新的文档与配置的 zone 匹配,则只能将其写入 zone 内的分片。

MongoDB 可以将不匹配已配置 zone 的文档写入 cluster 中的任何分片。

注意 上述行为要求 cluster 处于稳定的 state 状态,没有任何块违反配置的 zone。有关详细信息,请参阅平衡器上的以下部分。

阅读操作

如果查询包含 shard key,MongoDB 可以将查询 route 到特定分片。

对于 example,MongoDB 可以在以下查询上尝试目标读取操作,因为它在查询文档中包含creation_date

photoDB = db.getSiblingDB("photoshare")
photoDB.data.find( { "creation_date" : ISODate("2015-01-01") } )

如果请求的文档属于recent zone 范围,MongoDB 会将此查询路由到 zone 内的分片,确保与 cluster-wide broadcast 读操作相比更快的读取

平衡器

平衡器 迁移块关于任何已配置的 zones 的相应分片。在迁移之前,分片可能包含违反配置的 zones 的块。平衡完成后,分片应仅包含其范围不违反其指定的 zones 的块。

添加或删除 zones 或 zone 范围可能会导致块迁移。根据数据集的大小和 zone 或 zone 范围影响的块数,这些迁移可能会影响 cluster performance。考虑在特定的预定 windows 期间 running 您的平衡器。有关如何设置调度窗口的教程,请参阅安排平衡窗口

安全

对于使用Role-Based 访问控制运行的分片群集,请作为在admin数据库上至少具有clusterManager角色的用户进行身份验证。

程序

您必须连接到mongos才能创建 zones 或 zone 范围。您无法通过直接连接到碎片来创建 zone 或 zone 范围。

禁用平衡器

必须在集合上禁用平衡器,以确保在配置新 zones 时不会发生迁移。

使用sh.disableBalancing(),指定集合的名称空间,以停止平衡器

sh.disableBalancing("photoshare.data")

使用sh.isBalancerRunning()检查 balancer process 当前是否正在运行。等到任何当前的平衡轮完成后再继续。

将每个分片添加到适当的 zone

shard0000添加到recent zone。

sh.addShardTag("shard0000", "recent")

shard0001添加到recent zone。

sh.addShardTag("shard0001", "recent")

shard0002添加到archive zone。

sh.addShardTag("shard0002", "archive")

您可以通过 running sh.status()查看分配给任何给定分片的 zone。

定义每个 zone 的范围

定义最近照片的范围并使用sh.addTagRange()方法将其关联到recent zone。这种方法要求:

  • 目标集合的完整命名空间。

  • 范围的包容性下限。

  • 范围的唯一上限。

  • zone。

sh.addTagRange(
  "photoshare.data",
  { "creation_date" : ISODate("2016-01-01") },
  { "creation_date" : MaxKey },
  "recent"
)

定义旧照片的范围,并使用sh.addTagRange()方法将其与archive zone 关联。这种方法要求:

  • 目标集合的完整命名空间。

  • 范围的包容性下限。

  • 范围的唯一上限。

  • zone。

sh.addTagRange(
  "photoshare.data",
  { "creation_date" : MinKey },
  { "creation_date" : ISODate("2016-01-01") },
  "archive"
)

MinKeyMaxKey是保留的比较特殊值。

启用 Balancer

Re-enable 平衡器重新平衡 cluster。

使用sh.enableBalancing(),指定集合的名称空间,以启动平衡器

sh.enableBalancing("photoshare.data")

使用sh.isBalancerRunning()检查 balancer process 当前是否正在运行。

查看更改

平衡器运行的下一个 time 时,它会在关于已配置的 zones 的分片上进行拆分迁移块。

平衡完成后,recent zone 中的分片应仅包含creation_date大于或等于ISODate("2016-01-01")的文档,而archive zone 中的分片应仅包含creation_date小于ISODate("2016-01-01")的文档。

您可以通过 running sh.status()确认块分布。

更新 Zone 范围

要更新分片范围,请将以下操作作为 cron job 或其他预定过程的一部分执行:

禁用平衡器

必须在集合上禁用平衡器,以确保在配置新 zones 时不会发生迁移。

使用sh.disableBalancing(),指定集合的名称空间,以停止平衡器

sh.disableBalancing("photoshare.data")

使用sh.isBalancerRunning()检查 balancer process 当前是否正在运行。等到任何当前的平衡轮完成后再继续。

删除旧的 shard zone 范围

使用sh.removeTagRange()方法删除旧的recent zone 范围。这种方法要求:

  • 目标集合的完整命名空间。

  • 范围的包容性下限。

  • 范围的唯一上限。

  • zone。

sh.removeTagRange(
  "photoshare.data",
  { "creation_date" : ISODate("2016-01-01") },
  { "creation_date" : MaxKey },
  "recent"
)

使用sh.removeTagRange()方法删除旧的archive zone 范围。这种方法要求:

  • 目标集合的完整命名空间。

  • 范围的包容性下限。

  • 范围的唯一上限。

  • zone。

sh.removeTagRange(
  "photoshare.data",
  { "creation_date" : MinKey },
  { "creation_date" : ISODate("2016-01-01") },
  "archive"
)

MinKeyMaxKey是保留的比较特殊值。

为每个 zone 添加新的 zone 范围

定义最近照片的范围并使用sh.addTagRange()方法将其关联到recent zone。这种方法要求:

  • 目标集合的完整命名空间。

  • 范围的包容性下限。

  • 范围的唯一上限。

  • zone。

sh.addTagRange(
  "photoshare.data",
  { "creation_date" : ISODate("2016-06-01") },
  { "creation_date" : MaxKey },
  "recent"
)

定义旧照片的范围,并使用sh.addTagRange()方法将其与archive zone 关联。这种方法要求:

  • 目标集合的完整命名空间。

  • 范围的包容性下限。

  • 范围的唯一上限。

  • zone。

sh.addTagRange(
  "photoshare.data",
  { "creation_date" : MinKey },
  { "creation_date" : ISODate("2016-06-01") },
  "archive"
)

MinKeyMaxKey是保留的比较特殊值。

启用 Balancer

Re-enable 平衡器重新平衡 cluster。

使用sh.enableBalancing(),指定集合的名称空间,以启动平衡器

sh.enableBalancing("photoshare.data")

使用sh.isBalancerRunning()检查 balancer process 当前是否正在运行。

查看更改

平衡器运行的下一个 time,它在必要时拆分块,并且在分片的迁移块中遵循配置的 zones。

在平衡之前,recent zone 中的分片仅包含creation_date大于或等于ISODate("2016-01-01")的文档,而archive zone 中的分片仅包含creation_date小于ISODate("2016-01-01")的文档。

平衡完成后,recent zone 中的分片应仅包含creation_date大于或等于ISODate("2016-06-01")的文档,而archive zone 中的分片应仅包含creation_date小于ISODate("2016-06-01")的文档。

您可以通过 running sh.status()确认块分布。