你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

实现最佳性能的最佳做法

Azure Managed Instance for Apache Cassandra 是针对纯开源 Apache Cassandra 群集的完全托管服务。 通过该服务,还可根据每个工作负载的具体需求来替代配置,从而在需要时实现最大的灵活性和控制。 本文提供有关如何优化性能的提示。

最佳设置和部署

复制因子、磁盘数、节点数和 SKU

由于 Azure 在大多数地区支持 3 个可用性区域,并且 Cassandra 托管实例将可用性区域映射到机架,因此我们建议选择具有高基数的分区键以避免热分区。 为了获得最佳级别的可靠性和容错性,强烈建议将复制因子配置为 3。 还建议将复制因子的倍数指定为节点数,例如 3、6、9 等。

对于你预配的磁盘数,我们使用 RAID 0。 因此,若要获取最佳 IOPS,需要检查所选 SKU 上的最大 IOPS 以及 P30 磁盘的 IOPS。 例如,Standard_DS14_v2 SKU 支持 51,200 个未缓存的 IOPS,而单个 P30 磁盘的基础性能为 5,000 个 IOPS。 因此,4 个磁盘的 IOPS 数为 20,000,这远远低于计算机的限制。

强烈建议针对 SKU 和磁盘数对工作负载进行广泛的基准测试。 如果 SKU 只有 8 个核心,基准测试尤其重要。 我们的研究表明,8 核心 CPU 仅适用于要求最低的工作负载,而大多数工作负载至少需要 16 个核心才能运行。

分析工作负载与事务工作负载

事务工作负载通常需要针对低延迟进行了优化的数据中心,而分析工作负载通常使用更复杂的查询,这需要更长的时间来执行。 在大多数情况下,需要单独的数据中心:

  • 一个针对低延迟进行优化
  • 一个针对分析工作负载进行优化

针对分析工作负载进行优化

建议客户为分析工作负载应用以下 cassandra.yaml 设置(请在此处了解如何应用它们)。

超时

Cassandra MI 默认值 分析工作负载的推荐值
read_request_timeout_in_ms    5,000   10,000
range_request_timeout_in_ms 10,000 20,000
counter_write_request_timeout_in_ms  5,000 10,000
cas_contention_timeout_in_ms 1,000 2,000
truncate_request_timeout_in_ms 60,000 120,000
slow_query_log_timeout_in_ms 500 1,000
roles_validity_in_ms 2,000 120,000
permissions_validity_in_ms 2,000 120,000

缓存

Cassandra MI 默认值 分析工作负载的推荐值
file_cache_size_in_mb 2,048 6,144

更多建议

Cassandra MI 默认值 分析工作负载的推荐值
commitlog_total_space_in_mb 8,192 16,384
column_index_size_in_kb 64 16
compaction_throughput_mb_per_sec 128 256

客户端设置

建议根据服务器上应用的超时来调高 Cassandra 客户端驱动程序超时。

针对低延迟进行优化

我们的默认设置已经适用于低延迟工作负载。 为了确保尾部延迟的最佳性能,我们强烈建议使用支持推测执行的客户端驱动程序并相应地配置客户端。 对于 Java V4 驱动程序,可在此处找到说明其工作原理以及如何启用策略的演示。

监视性能瓶颈

CPU 性能

与每个数据库系统一样,如果 CPU 利用率约为 50%,并且始终不会超过 80%,那么 Cassandra 效果最佳。 可通过门户的“监视”中的“指标”选项卡查看 CPU 指标:

Screenshot of CPU metrics.

如果大多数节点的 CPU 利用率始终超过 80%,则数据库将过载,表现为多个客户端超时。 在这种情况下,建议还要执行以下操作:

  • 垂直纵向扩展到具有更多 CPU 核心的 SKU(尤其是核心数仅为 8 或更少时)。
  • 通过添加更多节点进行水平缩放(如前所述,节点数应为复制因子的倍数)。

如果只有几个节点的 CPU 利用率高,而对于其他节点来说利用率低,则表示热分区并需要进一步调查。

注意

Azure 门户、Azure CLI 和 ARM 模板部署支持更改 SKU。 可以部署/编辑 ARM 模板,并将 SKU 替换为以下选项之一。

  • Standard_E8s_v4
  • Standard_E16s_v4
  • Standard_E20s_v4
  • Standard_E32s_v4
  • Standard_DS13_v2
  • Standard_DS14_v2
  • Standard_D8s_v4
  • Standard_D16s_v4
  • Standard_D32s_v4
  • Standard_L8s_v3
  • Standard_L16s_v3
  • Standard_L32s_v3
  • Standard_L8as_v3
  • Standard_L16as_v3
  • Standard_L32as_v3

请注意,目前我们不支持跨 SKU 系列的转换。 例如,如果你目前拥有 Standard_DS13_v2,但有兴趣升级到更大的 SKU(例如 Standard_DS14_v2),则此选项不可用。 但是,你可以通过创建支持工单来请求升级到更高的 SKU。

磁盘性能

服务在 Azure P30 托管磁盘上运行,允许“突发 IOPS”。 当涉及到与磁盘相关的性能瓶颈时,需要仔细监视。 在这种情况下,请务必查看 IOPS 指标:

Screenshot of disk I/O metrics.

如果指标显示下面一个或全部特征,则可能表明你需要纵向扩展。

  • 始终高于或等于基本 IOPS 数(请记住,将 5,000 IOPS 乘以每个节点的磁盘数可得到此数字)。
  • 始终高于或等于 SKU 允许写入操作使用的最大 IOPS 数。
  • SKU 支持缓存存储(通过写入缓存),并且此数字小于托管磁盘中的 IOPS 数(这是读取 IOPS 的上限)。

如果只看到几个节点的 IOPS 数增加,那么你可能有热分区,并需要查看数据是否存在潜在的倾斜。

如果 IOPS 数低于所选 SKU 支持的数目,但大于或等于磁盘 IOPS 数,你可执行以下操作:

  • 添加更多磁盘来提高性能。 要增加磁盘,需要提出支持案例。
  • 通过添加更多节点来纵向扩展数据中心

如果 IOPS 数超过 SKU 支持的最大数,你可以:

有关详细信息,请参阅虚拟机和磁盘性能

网络性能

在大多数情况下,网络性能是足够的。 但是,如果你经常流式处理数据(录入频繁的水平纵向扩展/纵向缩减),或者存在大量的入口/出口数据移动,这可能会成为一个问题。 你可能需要评估 SKU 的网络性能。 例如,Standard_DS14_v2 SKU 支持 12,000 Mb/s,将其与指标中的传入/传出节点数进行比较:

Screenshot of network metrics.

如果只看到为少量节点提升了网络,那么你可能具有热分区,并需要查看数据分布和/或访问模式是否存在潜在的倾斜。

  • 垂直纵向扩展到支持更多网络 I/O 的其他 SKU。
  • 通过添加更多节点水平纵向扩展群集。

连接的客户端数太多

应该对部署进行计划和预配,以支持应用程序所需延迟要求的最大并行请求数。 对于给定的部署,在超过最低阈值的情况下向系统引入更多负载会增加总体延迟。 监视连接的客户端数,确保没有超过可容忍的限制。

Screenshot of connected client metrics.

磁盘空间

在大多数情况下,有足够的磁盘空间,因为默认部署针对 IOPS 进行了优化,使磁盘利用率较低。 不过,建议偶尔查看磁盘空间指标。 Cassandra 会积聚大量磁盘空间,然后在触发压缩时减少磁盘空间。 因此,请务必查看较长时间内的磁盘使用情况来确定趋势,例如压缩无法回收空间。

注意

为了确保压缩的可用空间,磁盘利用率应保持在 50% 左右。

如果只在几个节点中看到这个行为,那么你可能具有热分区,并需要查看数据分布和/或访问模式是否存在潜在的倾斜。

  • 添加更多磁盘,但请注意 SKU 施加的 IOPS 限制
  • 水平纵向扩展群集

JVM 内存

我们的默认公式是将 VM 的一般内存分配给 JVM,上限为 31 GB - 在大多数情况下,这在性能和内存之间达到了良好平衡。 某些工作负载,尤其是具有频繁跨分区读取或范围扫描的工作负载,可能会面临内存挑战。

在大多数情况下,Java 垃圾回收器会有效地回收内存,但特别是当 CPU 利用率通常超过 80% 时,没有足够的 CPU 周期可供垃圾回收器使用。 因此在解决内存问题之前,应先解决所有 CPU 性能问题。

如果 CPU 利用率在 70% 以下徘徊,并且垃圾回收无法回收内存,你可能需要更多的 JVM 内存。 如果你使用的是内存有限的 SKU,则尤其如此。 在大多数情况下,除了 CQL 查询中 limit 中选择的内容,还需要查看查询和客户端设置并减少 fetch_size

如果确实需要更多内存,你可以:

  • 向我们提交票证来调高 JVM 内存设置
  • 垂直扩展到具有更多可用内存的 SKU

逻辑删除

我们使用回收器每 7 天运行一次修复,这会删除 TTL 已到期的行(称为“逻辑删除”)。 某些工作负载具有更频繁的删除,并在 Cassandra 日志中显示 Read 96 live rows and 5035 tombstone cells for query SELECT ...; token <token> (see tombstone_warn_threshold) 之类的警告,甚至显示指示由于逻辑删除过多而无法完成查询的错误。

在查询未得到满足的情况下执行的短期缓解措施是将 Cassandra 配置中的 tombstone_failure_threshold从默认值 100,000 增加到更高的值。

除此之外,还建议查看密钥空间上的 TTL,并可能每天运行一次修复来清除更多的逻辑删除。 如果 TTL 较短(例如不到两天),并且数据流入但被快速删除,建议查看压缩策略并首选Leveled Compaction Strategy。 在某些情况下,此类操作可能表明需要查看数据模型。

批处理警告

CassandraLogs 和潜在相关故障中可能会看到此警告:

Batch for [<table>] is of size 6.740KiB, exceeding specified threshold of 5.000KiB by 1.740KiB.

在这种情况下,应查看查询,使其低于建议的批处理大小。 在极少数情况下,作为短期缓解措施,可以在 Cassandra 配置中将 batch_size_fail_threshold_in_kb 从默认值 50 增加到更高的值。  

大型分区警告

CassandraLogs 中可能会看到此警告:

Writing large partition <table> (105.426MiB) to sstable <file>

这表示数据模型中存在问题。 这里有一篇堆栈溢出文章,它更详细地进行了介绍。 这可能会导致严重的性能问题,需要解决。

专用优化

压缩

Cassandra 允许在创建表时选择适当的压缩算法(请参阅压缩)。默认值为 LZ4,这对于吞吐量和 CPU 来说都很好,但会在磁盘上占用更多空间。 使用 Zstd(Cassandra 4.0 及更高版本)可节省约 12% 的空间,且 CPU 开销最小。

优化内存表堆空间

对于 cassandra.yaml 中的 memtable_heap_space,默认使用 1/4 的 JVM 堆。 对于面向写操作的应用程序和/或在内存较小的 SKU 上,这可能会导致频繁刷新和碎片化的 sstable,因而需要更多压缩。 在这种情况下,将其增加到至少 4048 可能是有益的,但需要仔细进行基准测试,以确保其他操作(例如读取)不受影响。

后续步骤

在本文中,我们介绍了实现最佳性能的一些最佳做法。 现在你可开始使用该群集了: