了解 Bigtable 的性能

本页面介绍了 Cloud Bigtable 在最佳条件下可提供的大致性能、可能会影响性能的因素,以及测试和排查 Bigtable 性能问题的提示。

典型工作负载下的性能

Bigtable 可提供高度可预测的线性扩缩性能。如果您避免了下文所述的性能下降的原因,则每个 Bigtable 节点都可提供以下大致吞吐量,具体取决于集群使用的存储空间类型:

存储空间类型 读取   写入   扫描
SSD 每秒最多 10000 行 每秒最多 10000 行 最多 220 MB/秒
HDD 每秒最多 500 行 每秒最多 10000 行 最多 180 MB/秒

这些估算值假设每行包含 1 KB 的数据。

一般来说,集群的性能会随着集群中节点数量的增加而线性提升。例如,如果您创建一个具有 10 个节点的 SSD 集群,则在典型的只读或只写工作负载下,该集群最多可以支持每秒 10 万行读取或写入。

规划 Bigtable 容量

在高吞吐量和低延时之间权衡取舍

在规划 Bigtable 集群时,请务必考虑吞吐量和延迟时间之间的权衡取舍。Bigtable 可用于多种应用,不同的用例可能有不同的优化目标。例如,对于批量数据处理作业,您可能会更关注吞吐量,而不那么关注延迟时间。另一方面,对于处理用户请求的在线服务,低延时的优先级可能高于吞吐量。因此,相应地规划容量非常重要。

当您优先考虑吞吐量时,虽然典型工作负载下的性能部分的数字是可实现的,但对于延迟敏感型应用,Bigtable 在此负载下的尾延迟时间可能会过高。通常,当一个集群的 CPU 负载低于 70% 时,Bigtable 可提供最佳延迟时间。但是,对于延迟敏感型应用,我们建议规划至少 2 倍于应用的最大 Bigtable QPS 的容量。此容量可确保您的 Bigtable 集群以低于 50% 的 CPU 负载运行,从而为前端服务提供低延时。流量高峰或密钥访问热点可能会导致集群中节点之间的不平衡流量,此容量还可为它们提供缓冲区。

针对 Bigtable 运行典型工作负载

在进行容量规划时,请始终针对 Bigtable 集群运行您自己的典型工作负载,以便确定应用的最佳资源分配。

Google 的 PerfKit Benchmarker 使用 YCSB 对云服务进行基准测试。您可以按照 Bigtable 的 PerfKitBenchmarker 教程为您自己的工作负载创建测试。进行上述操作时,您应调整基准配置 yaml 文件中的参数,以确保生成的基准反映生产环境中的以下特性:

  • 表的总大小。您可以按比例设置,但至少为 100 GB。
  • 行数据形状(行键大小、列数、行数据大小等)
  • 数据访问模式(行键分布)
  • 读取与写入的混合

如需了解更多最佳做法,请参阅使用 Bigtable 测试性能

性能下降的原因

以下几个因素可能会导致 Bigtable 的执行速度低于以上所示估算值:

  • 在单个读取请求中读取大量非连续行键或行范围。Bigtable 会扫描表并按顺序读取所请求的行。这种并行性影响会影响总体并造成任何命中热节点可增加尾巴延迟时间。如需了解详情,请参阅读取和性能
  • 表架构的设计不正确。为了使 Bigtable 实现良好性能,您需要设计一个可以将读写操作均匀分布到每个表的架构,这至关重要。如需了解详情,请参阅设计架构
  • Bigtable 表中的行包含大量数据。以上所示性能估计假设每行包含 1 KB的数据。您可以每行读取和写入更多数据,但增加每行的数据量也会减少每秒的行数。
  • Bigtable 表中的行包含大量单元格。Bigtable 需要一些时间来处理一行中的每个单元格。此外,每个单元格也会对存储在表中并通过网络发送的数据量增加一些开销。例如,如果您要存储 1 KB(1024 字节)的数据,那么将这些数据存储在一个单元格中,要比将数据分布在 1024 个均包含一个字节的单元格中更具空间效率。如果您将数据拆分到超出必要数量的单元格中,则可能无法获得最佳性能。 如果行包含大量单元,因为列包含多个带时间戳的数据版本,请考虑仅保留最新值。对于现有表,另一个选项是在每次重写时发送先前所有版本的删除。
  • Bigtable 集群没有足够的节点。如果您的 Bigtable 集群过载,添加更多节点可以提高性能。可以使用监控工具检查集群是否过载。
  • Bigtable 集群最近扩大或缩小了规模。在增加集群中的节点数量进行纵向扩容后,在负载下最多可能需要 20 分钟才能在集群中显著提升性能。当您减少集群中的节点数量进行纵向缩容时,请尽量不要在 10 分钟内将集群大小降低 10% 以上,以最大限度地减少延迟时间急剧增加的情况。
  • Bigtable 集群使用 HDD 磁盘。在大多数情况下,您的集群应使用 SSD 磁盘,其性能明显优于 HDD 磁盘。如需了解详情,请参阅在 SSD 和 HDD 存储空间之间进行选择
  • 网络连接存在问题。网络问题可能会降低吞吐量,并导致读写时间比通常要长。具体而言,如果您的客户端与 Bigtable 集群运行的地区不同,或者您的客户端在 Google Cloud 外部运行,则可能会出现问题。

由于性能会因工作负载的不同而发生变化,因此您应该使用自己的工作负载进行测试以获取最准确的基准。

复制和性能

启用复制将会影响 Bigtable 实例的性能。这对某些指标而言是正面影响,而对于其他指标则是负面影响。您应该先了解性能可能受到的影响,然后再决定是否启用复制。

读取吞吐量

复制可以提高读取吞吐量,尤其是在使用多集群路由的情况下。此外,复制可将您的 Bigtable 数据放置在地理位置上更接近应用的用户,从而减少读取延迟时间。

写入吞吐量

虽然复制可以提高可用性和读取性能,但它不会增加写入吞吐量。对一个集群的写入必须复制到实例中的所有其他集群。因此,每个集群都会消耗 CPU 资源以从其他集群中拉取更改。实际上,写入吞吐量可能会下降,因为复制会要求每个集群执行更多工作。

例如,假设您有一个单集群实例,且该集群包含 3 个节点:

包含 3 个节点的单集群实例

如果您向集群添加节点,这对写入吞吐量产生的影响,与向实例添加第二个含 3 个节点的集群来启用复制所产生的影响不同。

向原始集群添加节点:您可以向集群添加 3 个节点(总共 6 个节点)。实例的写入吞吐量会加倍,但实例的数据仅在一个地区中可用:

包含 6 个节点的单集群实例

使用复制:此外,您也可以添加第二个含 3 个节点(总共 6 个节点)的集群。现在,出现以下情况时该实例将各个数据写入两次:首次接收写入时以及将写入复制到另一个集群时。写入吞吐量不会增加,还有可能会下降,但是您将从数据在两个不同地区可用中获益。

包含 6 个节点的双集群实例

在这些示例中,即使每个实例的集群总共有 6 个节点,单集群实例所处理的写入吞吐量也可以是复制实例可以处理的两倍。

复制延迟时间

使用多集群路由时,Bigtable 的复制最终一致。一般来说,距离越远,复制数据需要更长的时间。相较于同一区域中的复制集群,不同区域中的复制集群的复制延迟时间通常更长。

应用配置文件和流量路由

根据您的用例,您将使用一个或多个应用配置文件来路由您的 Cloud Bigtable 流量。每个应用配置文件都使用多集群或单集群路由。选择的路由可能会影响性能。

多集群路由可将延迟时间减至最低。从应用的角度来看,使用多集群路由的应用配置文件会自动将请求路由到实例中最近的集群,然后写入将会复制到实例中的其他集群。这种自动选择的最短距离会使延迟时间达到可能限度内的最低值。

使用单集群路由的应用配置文件可能是某些用例(例如分离工作负载或在单集群上具有“执行写入后读取”语义)的最佳选择,但它不会像多集群路由那样减少延迟时间。

如需了解如何为这些和其他用例配置您的应用配置文件,请参阅复制设置的示例

Bigtable 如何实时优化您的数据

为了存储每个表的基础数据,Bigtable 会将数据分成多个片,您可以在 Bigtable 集群的各节点之间移动这些片。这种存储方法使 Bigtable 能够在长时间运行过程中,使用以下两种不同的策略来优化您的数据:

  1. Bigtable 尝试在每个 Bigtable 节点上存储大致相同数量的数据。
  2. Bigtable 尝试在所有 Bigtable 节点中平均分配读取和写入操作。

有时候这些策略会相互冲突。例如,如果一个片所对应的行被读取的频率极高,则 Bigtable 可能会将该片存储在其自己的节点上,即使这会导致一些节点存储比其他节点更多的数据。

在此过程中,Bigtable 可能还会将片拆分成两个或更多个更小的片,以减小片的大小或隔离现有片中的常用行。

以下部分对这些策略分别进行了更为详细的介绍。

将数据量分配到各节点

随着您向 Bigtable 表中写入的数据越来越多,Bigtable 会将表中的数据分成若干片。每个片包含表中一定范围的连续行。

如果您只向表中写入了少量数据,Bigtable 会将所有片存储在集群的单个节点上:

单个节点上包含四个片的集群。

随着累积的片越来越多,Bigtable 会将部分片移至集群的其他节点,以使数据量在整个集群中更均匀地分布:

其他片分布在多个节点上。

将读写操作均匀分布到各节点

如果您已经正确地设计您的架构,那么读写操作应会相当均匀地分配到整个表中。但在某些情况下,您无法避免比其他人更频繁地访问某些行。Bigtable 会在将片平均分配到各节点时考虑读写操作,从而可帮助您应对这些情况。

例如,假设 25% 的读取内容将进入集群的少量片中,并且读取操作均匀分布在所有其他片中:

总共 48 个片中,25% 的读取针对 3 个片。

Bigtable 将重新分配现有的片,以便读取操作尽可能均匀地分布在整个集群中:

三个常用片被隔离到各自的节点上。

使用 Bigtable 测试性能

如果您要对依赖于 Bigtable 的应用运行性能测试,请在规划和执行测试时遵循以下准则:

  • 使用足够的数据进行测试
    • 如果生产实例中的表包含的每个节点的总数据量不超过 100 GB,请使用数据量相同的表进行测试。
    • 如果表包含的每个节点的数据超过 100 GB,请使用每个节点至少包含 100 GB 的数据的表进行测试。例如,如果您的生产实例具有一个四节点集群,并且实例中的表总共包含 1 TB 的数据,请使用至少 400 GB 的表运行测试。
  • 使用单个表进行测试
  • 每个节点保持低于建议的存储空间利用率。如需了解详情,请参阅每个节点的存储空间利用率
  • 在测试之前,请先运行几分钟重载预测试。此步骤旨在让 Bigtable 可以根据其所遵循的访问模式使您的各节点之间的数据保持平衡。
  • 运行您的测试至少 10 分钟。此步骤旨在让 Bigtable 能够进一步优化您的数据,并有助于确保您的测试将包括对磁盘数据的读取以及内存中缓存数据的读取。

性能问题排查

如果您觉得 Bigtable 可能在您的应用中造成了性能瓶颈,请务必进行以下所有检查:

  • 检查您的表的 Key Visualizer 扫描。适用于 Bigtable 的 Key Visualizer 工具可进行每日扫描,显示集群中每个表的使用模式。Key Visualizer 可以检查您的使用模式是否会导致不良结果,例如特定行上的热点或 CPU 利用率过高。了解如何开始使用 Key Visualizer
  • 尝试注释掉用于执行 Bigtable 读写操作的代码。如果性能问题消失,则说明 Bigtable 的使用方式可能导致性能欠佳。如果性能问题依然存在,则说明问题可能与 Bigtable 无关。
  • 确保您创建尽可能少的客户端。为 Bigtable 创建客户端的成本相对较高。因此,您应该尽可能创建最少的客户端:

    • 如果您使用复制功能,或者您使用应用配置文件来识别路由到实例的不同类型的流量,请为每个应用配置文件创建一个客户端,并在整个应用中共享客户端。
    • 如果您不使用复制或应用配置文件,请创建单个客户端并在整个应用中共享该客户端。

    如果您使用的是 Java 版 HBase 客户端,您需要创建 Connection 连接对象而非客户端,因此您应该创建尽可能少的连接。

  • 确保您从表中读取和写入的是许多不同的行。当读写操作均匀分布在整个表中时,Bigtable 性能最佳,这有助于 Bigtable 将工作负载分布到集群的所有节点上。如果读取和写入操作不能分布在所有 Bigtable 节点上,性能则将受到影响。

    如果发现只读取和写入了少量行,您可能需要重新设计您的架构,以使读写操作更加均匀地分布。

  • 验证 Cloud Bigtable 所呈现的读取和写入性能大致相同。如果您发现读取速度比写入速度快得多,那么说明可能是您正在尝试读取的行键不存在或部分行键仅包含少量行。

    为了在读取和写入操作之间进行有效的比较,至少 90% 的读取操作应返回有效结果。另外,如果您读取的行键范围比较大,应根据该范围内的实际行数来衡量性能,而不是根据可能存在的最大行数。

  • 使用正确类型的数据写入请求。选择最佳数据写入方式有助于保持高性能。

  • 检查单行的延迟时间。如果您在发送 ReadRows 请求时观察到意外延迟,则可以检查请求第一行的延迟时间,以缩小原因的范围。默认情况下,ReadRows 请求的整体延迟时间包括请求中每一行的延迟时间以及各行之间的处理时间。如果整体延迟时间较高,但第一行延迟时间较低,这表明延迟时间是由请求数量或处理时间所致,而不是 Bigtable 问题导致。

    如果您使用的是 Java 版 Cloud Bigtable 客户端库,则可以在启用客户端指标之后,在 Cloud Console Metrics Explorer 中查看 read_rows_first_row_latency 指标。

后续步骤