扩缩

扩缩集群是为集群添加或移除节点以响应集群工作负载或数据存储需求变化的过程。您还可以根据集群的 CPU 使用率等指标来扩缩 Bigtable 集群,这会很有用。例如,如果集群的负载很高,并且其 CPU 使用率也很高,您可以向集群添加节点,直到其 CPU 使用率有所下降为止。您也可以将不常使用的节点从集群中移除,以节省资金。

扩缩选项

您可以通过以下方式扩缩 Bigtable 集群:

在大多数情况下,如果您希望使用自动扩缩功能,则应使用 Bigtable 的内置自动扩缩功能。启用此功能后,Bigtable 会持续监控集群,并根据您的设置自动调整节点数量。

限制

在为 Bigtable 集群启用自动扩缩或设置编程扩缩之前,请考虑以下限制。

节点可用性

无论集群启用了手动节点分配还是自动扩缩,节点配额都适用。如需了解详情,请参阅配额和节点可用性

节点重新均衡时出现延迟现象

将节点添加到集群后,负载繁重的集群可能需要长达 20 分钟的时间才能表现出性能显著提升。因此,如果您的工作负载涉及时间短暂的突发高负载活动,则根据 CPU 负载向集群添加节点并不会提升性能,因为等到 Bigtable 重新均衡数据时,这种短暂的活动已经结束。

若要规划此延迟时间,您可以先通过编程方式或通过 Google Cloud 控制台向集群添加节点,然后再增加集群的负载。这种方法可让 Bigtable 在工作负载增加之前有时间将您的数据重新平衡到增加的节点。在使用手动节点分配的集群上,更改节点数量。在使用自动扩缩功能的集群上,更改节点数下限。流量恢复正常后,更改回原先的节点设置。

因纵向缩容过快而导致的延迟增加

当您减少集群中的节点数量进行纵向缩容时,请尽量不要在 10 分钟内将集群大小降低 10% 以上。如果集群中的剩余节点暂时不堪重负,则纵向缩容过快可能会导致性能问题,例如延迟增加。

架构设计问题

如果表的架构设计存在问题,则向 Bigtable 集群添加节点可能不会提升性能。例如,如果您要对表的单个行执行大量读取或写入操作,则所有读取或写入操作都将转至集群的同一节点,因此,添加节点并不会提升性能。相反,如果读取和写入操作均匀分布到表的各行中,则添加节点通常会使性能有所提升。

如需详细了解如何设计架构以有效调节 Bigtable 的规模,请参阅设计您的架构

如何以编程方式扩缩 Bigtable

在某些情况下,您可能希望编写自己的应用来扩缩 Bigtable 集群。本部分介绍了如何以编程方式扩缩集群,并提供了示例代码供您参考。此外,本页面还介绍了在设置编程扩缩机制之前您应该注意的一些限制。

Bigtable 通过 Cloud Monitoring API 提供各种指标。您可以通过编程方式监控集群的这些指标,然后使用其中一个 Bigtable 客户端库或 Google Cloud CLI,根据当前指标添加或移除节点。调整完集群大小后,您可以通过 Google Cloud 控制台、Cloud Monitoring 自定义信息中心或以编程方式监控其性能

监控 API 指标

Monitoring API 提供了各种指标,可供您用来监控集群的当前状态。以编程方式扩缩集群的规模时,最有用的一些指标如下:

  • bigtable.googleapis.com/cluster/cpu_load:集群的 CPU 负载。
  • bigtable.googleapis.com/cluster/node_count:集群中的节点数。
  • bigtable.googleapis.com/cluster/storage_utilization:使用的存储空间占总存储空间容量的比例。
  • bigtable.googleapis.com/server/latencies:某个表对应的服务器请求延迟的分布情况。

示例代码

您可以将下面所列的其中一种示例工具作为起点来创建自己的编程调节工具:

示例工具会在 Bigtable 集群的 CPU 负载超过指定值时向该集群添加节点。同样,它们也会在 Bigtable 集群的 CPU 负载低于指定值时从该集群中移除节点。要运行示例工具,请按照 GitHub 上针对每个示例的说明进行操作。

示例工具使用以下代码收集集群 CPU 负载的相关信息:

Java

如需了解如何安装和使用 Bigtable 的客户端库,请参阅 Bigtable 客户端库

如需向 Bigtable 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为客户端库设置身份验证

Timestamp now = timeXMinutesAgo(0);
Timestamp fiveMinutesAgo = timeXMinutesAgo(5);
TimeInterval interval =
    TimeInterval.newBuilder().setStartTime(fiveMinutesAgo).setEndTime(now).build();
String filter = "metric.type=\"" + CPU_METRIC + "\"";
ListTimeSeriesPagedResponse response =
    metricServiceClient.listTimeSeries(projectName, filter, interval, TimeSeriesView.FULL);
return response.getPage().getValues().iterator().next().getPointsList().get(0);

Python

如需了解如何安装和使用 Bigtable 的客户端库,请参阅 Bigtable 客户端库

如需向 Bigtable 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为客户端库设置身份验证

client = monitoring_v3.MetricServiceClient()
cpu_query = query.Query(
    client,
    project=PROJECT,
    metric_type="bigtable.googleapis.com/" "cluster/cpu_load",
    minutes=5,
)
cpu_query = cpu_query.select_resources(
    instance=bigtable_instance, cluster=bigtable_cluster
)
cpu = next(cpu_query.iter())
return cpu.points[0].value.double_value

示例工具使用 CPU 客户端库,根据 CPU 负载调整集群的大小:

Java

如需了解如何安装和使用 Bigtable 的客户端库,请参阅 Bigtable 客户端库

如需向 Bigtable 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为客户端库设置身份验证

double latestValue = getLatestValue().getValue().getDoubleValue();
if (latestValue < CPU_PERCENT_TO_DOWNSCALE) {
  int clusterSize = clusterUtility.getClusterNodeCount(clusterId, zoneId);
  if (clusterSize > MIN_NODE_COUNT) {
    clusterUtility.setClusterSize(clusterId, zoneId,
      Math.max(clusterSize - SIZE_CHANGE_STEP, MIN_NODE_COUNT));
  }
} else if (latestValue > CPU_PERCENT_TO_UPSCALE) {
  int clusterSize = clusterUtility.getClusterNodeCount(clusterId, zoneId);
  if (clusterSize <= MAX_NODE_COUNT) {
    clusterUtility.setClusterSize(clusterId, zoneId,
      Math.min(clusterSize + SIZE_CHANGE_STEP, MAX_NODE_COUNT));
  }
}

Python

如需了解如何安装和使用 Bigtable 的客户端库,请参阅 Bigtable 客户端库

如需向 Bigtable 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为客户端库设置身份验证

bigtable_client = bigtable.Client(admin=True)
instance = bigtable_client.instance(bigtable_instance)
instance.reload()

if instance.type_ == enums.Instance.Type.DEVELOPMENT:
    raise ValueError("Development instances cannot be scaled.")

cluster = instance.cluster(bigtable_cluster)
cluster.reload()

current_node_count = cluster.serve_nodes

if scale_up:
    if current_node_count < max_node_count:
        new_node_count = min(current_node_count + size_change_step, max_node_count)
        cluster.serve_nodes = new_node_count
        operation = cluster.update()
        response = operation.result(480)
        logger.info(
            "Scaled up from {} to {} nodes for {}.".format(
                current_node_count, new_node_count, response.name
            )
        )
else:
    if current_node_count > min_node_count:
        new_node_count = max(current_node_count - size_change_step, min_node_count)
        cluster.serve_nodes = new_node_count
        operation = cluster.update()
        response = operation.result(480)
        logger.info(
            "Scaled down from {} to {} nodes for {}.".format(
                current_node_count, new_node_count, response.name
            )
        )

调整完集群大小后,您可以使用 Google Cloud 控制台Cloud Monitoring 自定义信息中心来监控集群性能随时间变化的情况。

后续步骤