Memorystore for Redis Cluster 最佳实践

本页面提供了有关如何以最佳方式使用 Memorystore for Redis Cluster 的指南。本页面还指出了需要避免的潜在问题。

内存管理最佳做法

本部分介绍了管理集群内存的策略,以便 Memorystore for Redis Cluster 能够高效地为客户端应用运行。

内存管理概念

  • 写入负载 - 在 Redis 集群中添加或更新键的数量和速度。写入负载可能从正常到非常高,具体取决于 Redis 用例和应用使用模式。

  • 逐出政策 - Memorystore for Redis Cluster 使用 volatile-lru 逐出政策。您可以使用 EXPIRE 等命令为键设置逐出。

监控具有正常写入负载的集群

查看 /cluster/memory/maximum_utilization 指标。如果 /cluster/memory/maximum_utilization 为 100% 或更低,则 Redis 集群在使用正常写入负载时表现良好。

不过,如果您的内存用量接近 100%,并且您预计数据用量会增加,则应扩大集群规模,以便为新数据腾出空间。

监控写入负载较高的集群

查看 /cluster/memory/maximum_utilization 指标。根据高写入负载的严重程度,您的集群可能会在达到以下阈值时遇到性能问题:

  • 如果 /cluster/memory/maximum_utilization 达到 65% 或更高,则非常高的写入负载可能会遇到问题。

  • 如果 /cluster/memory/maximum_utilization 达到 85% 或更高,则中等偏高的写入负载可能会遇到问题。

在这些情况下,您应扩大集群规模以提高性能。

如果您遇到问题,或者担心集群的写入负载过高,请与 Google Cloud 支持团队联系。

扩缩分片

扩缩集群中的分片数量时,您应在写入量较低的时段进行扩缩。在高写入负载期间进行扩缩可能会因复制或槽迁移导致的内存开销而给集群带来内存压力。

如果您的 Redis 用例使用键逐出,则伸缩到较小的集群大小可能会降低缓存命中率。不过,在这种情况下,您无需担心数据丢失,因为键逐出是预期行为。

对于您不想丢失键的 Redis 用例,您应该仅缩容到仍有足够空间容纳数据的较小集群。新的目标分片数量应至少允许数据使用 1.5 倍的内存。换句话说,您应该预配足够的分片,以容纳集群中数据量的 1.5 倍。您可以使用 /cluster/memory/total_used_memory 指标查看集群中存储的数据量。

CPU 使用率最佳实践

如果发生意外的可用区级服务中断,由于不可用可用区中的节点容量丢失,集群的 CPU 资源会减少。我们建议使用高可用性集群。在发生服务中断时,每个分片使用多个副本(而不是每个分片使用一个副本)可提供额外的 CPU 资源。每个分片最多可以有五个副本。

此外,我们建议您管理节点 CPU 使用率,以便在发生意外可用区服务中断时,节点有足够的 CPU 开销来处理因容量损失而产生的额外流量。您应使用主线程 CPU 秒数 /cluster/cpu/maximum_utilization 指标监控主实例和副本的 CPU 使用情况。

根据您为每个节点预配的副本数量,我们建议您采用以下 /cluster/cpu/maximum_utilization CPU 使用率目标:

  • 对于每个节点有一个副本的集群,主实例的 /cluster/cpu/maximum_utilization 目标值为 0.5 秒,副本的目标值为 0.5 秒。
  • 对于每个节点具有两个或更多副本的集群,主副本的目标 /cluster/cpu/maximum_utilization 值为 0.9 秒,每个副本的目标值为 0.5 秒。

如果该指标的值超出这些建议值,我们建议您增加集群中的分片数量。如果集群的副本数量少于 5 个,您还可以增加副本数量,最多可增加到 5 个。

如果集群的 CPU 利用率较高或集群的资源耗尽(例如,连接过多),则集群可能会出现异常行为,并且外部指标可能会缺失。

占用大量资源的 Redis 命令

我们强烈建议您避免使用资源密集型 Redis 命令。使用这些命令可能会导致以下性能问题:

  • 延迟时间较长和客户端超时
  • 由增加内存用量的命令引起的内存压力
  • 由于 Redis 主线程被阻塞,节点复制和同步期间发生数据丢失
  • 健康检查、可观测性和复制功能不足

下表列出了资源密集型 Redis 命令的示例,并为您提供了资源高效型替代方案。

类别 资源密集型命令 资源高效型替代方案
针对整个键空间运行 KEYS SCAN
针对长度可变的密钥集运行 LRANGE 限制查询所用范围的大小。
ZRANGE 限制查询所用范围的大小。
HGETALL HSCAN
SMEMBERS SSCAN
阻止脚本运行 EVAL 确保脚本不会无限期运行。
EVALSHA 确保脚本不会无限期运行。
移除文件和链接 DEL UNLINK
发布和订阅 PUBLISH SPUBLISH
SUBSCRIBE SSUBSCRIBE

伸缩阈值的最佳实践

扩缩阈值场景分为以下几类:

  • 根据内存利用率进行扩缩
  • 根据 CPU 利用率进行扩缩
  • 通过扩缩来缓解热点问题

如果您的工作负载依赖于逐出键,则 Google 不建议针对 CPU 或内存利用率进行缩容。在这些工作负载中,内存利用率通常会在自动逐出发生之前达到其最大容量。由此产生的内存峰值会阻止缩容操作。

以下部分详细介绍了可能需要伸缩的常见场景和指标阈值。

内存利用率伸缩

如需确定何时根据内存用量进行扩缩,请监控 /cluster/memory/average_utilization 和 /cluster/memory/maximum_utilization 指标。如需详细了解这些指标,请参阅支持的监控指标。

如果您的集群满足以下任一条件,请考虑触发扩容操作:

  • 集群的平均内存利用率超过了建议的阈值 70%。
  • 最大内存利用率超过 80%,平均内存利用率超过 50%。

如果您的集群满足以下任一条件,请考虑触发缩容操作:

  • 集群的平均内存利用率低于建议的阈值 50%。
  • 最大内存利用率降至 60% 以下,平均内存利用率降至 40% 以下。

CPU 利用率伸缩

如需确定何时根据 CPU 用量进行扩缩,请监控 /cluster/cpu/average_utilization 和 /cluster/cpu/maximum_utilization 指标。

如果您的集群满足以下任一条件,请考虑触发扩容操作:

  • 集群的平均 CPU 利用率超过了建议的阈值 70%。
  • 最大 CPU 利用率超过 80%,平均 CPU 利用率超过 50%。

如果您的集群满足以下任一条件,请考虑触发缩容操作:

  • 集群的平均 CPU 利用率低于建议的阈值 50%。
  • 最大 CPU 利用率降至 60% 以下,平均 CPU 利用率降至 40% 以下。

通过扩缩来缓解热点问题

Memorystore for Redis Cluster 提供同一指标的平均值和最大值变体,您可以使用这些变体来识别该指标系列的“热点”。最大值表示负载最重的集群节点,而平均值表示整个集群的负载。如果最大值明显高于平均值,则表示特定节点负载过高(热点)。为解决此问题,我们建议您横向扩容集群。如需了解详情,请参阅扩缩集群容量。

当您观察到平均变异和最大变异之间存在显著差异时,可以针对集群节点运行 INFO memory 和 INFO cpu 命令,直接从集群收集实时数据。如需详细了解如何使用这些命令,请参阅 Redis 文档中的 INFO。

Redis 客户端最佳实践

连接到集群时,您的应用必须使用集群感知型 Redis 客户端。如需查看集群感知型客户端和示例配置的示例,请参阅客户端库代码示例。客户端必须维护哈希槽到集群中相应节点的映射,以便将请求发送到正确的节点,并避免集群重定向导致的性能开销。

客户映射

在以下情况下,客户端必须获取槽和映射节点的完整列表:

  • 客户端初始化后,必须填充初始槽到节点的映射。

  • 当从服务器收到 MOVED 重定向时,例如在故障切换情况下,当之前的主节点服务的所有槽都由副本接管时,或者在槽从源主节点移动到目标主节点时重新分片。

  • 从服务器收到 CLUSTERDOWN 错误,或与特定服务器的连接持续超时。

  • 从服务器收到 READONLY 错误时。当主实例降级为副本时,可能会发生这种情况。

  • 此外,客户端应定期刷新拓扑,以便为任何更改做好准备,并了解可能不会导致服务器重定向或错误(例如添加新副本节点时)的更改。请注意,在拓扑刷新过程中,还应关闭所有过时连接,以减少在命令运行时处理失败连接的需求。

客户端发现

客户端发现通常通过向 Redis 服务器发出 CLUSTER SLOT、CLUSTER NODE 或 CLUSTER SHARDS 命令来完成。我们建议您使用 CLUSTER SHARDS 命令。CLUSTER SHARDS 通过提供更高效、更可扩展的集群表示,取代了 CLUSTER SLOTS 命令(已弃用)。

集群客户端发现命令的响应大小可能会因集群大小和拓扑而异。节点越多的大型集群生成的响应越大。因此,请务必确保执行集群拓扑发现的客户端数量不会无限制地增长。

这些拓扑刷新在 Redis 服务器上开销很大,但对应用可用性也很重要。因此,请务必确保每个客户端在任何给定时间都只发出一个发现请求(并将结果缓存在内存中),并且发出请求的客户端数量保持在一定范围内,以避免服务器过载。

例如,当客户端应用启动或与服务器断开连接,并且必须执行集群发现时,一个常见错误是客户端应用在重试时发出多个重新连接和发现请求,而没有添加指数退避算法。这可能会导致 Redis 服务器长时间无响应,从而导致 CPU 利用率非常高。

避免 Redis 上的发现过载

为缓解连接和发现请求突然涌入造成的影响,我们建议您采取以下措施:

  • 实现一个大小有限且较小的客户端连接池,以限制来自客户端应用的并发传入连接数。

  • 当客户端因超时而与服务器断开连接时,请使用抖动的指数退避算法重试。这有助于避免多个客户端同时向服务器发送大量请求。

  • 使用 Memorystore for Redis Cluster 发现端点执行集群发现。发现端点具有高可用性,并且在集群中的所有节点之间实现负载均衡。此外,发现端点会尝试将集群发现请求路由到具有最新拓扑视图的节点。

检测并处理无响应的连接

我们强烈建议您将客户端应用配置为检测与 Memorystore for Redis Cluster 的无响应连接。检测到无响应的连接时,客户端必须重置该连接。为了构建弹性应用,我们建议 采用以下客户端配置:

  • 配置 TCP keep-alive 参数:设置 TCP keepalive time、TCP keepalive interval 和 TCP keepalive probes 参数,以便客户端主动检测并丢弃无响应的连接,即使连接处于空闲状态也是如此。例如,如果您将 TCP keepalive time 参数设置为 30 秒,将 TCP keepalive interval 设置为 10 秒,将 TCP keepalive probes 设置为 3,则客户端会在一分钟内重置无响应的空闲连接。
  • 配置 TCP 用户超时:在客户端中设置此超时,以重置具有未完成请求且停止响应的连接。例如,如果您将超时设置为 15 秒,则客户端会在 15 秒后重置具有未完成请求的无响应连接。

持久性最佳实践

本部分介绍了持久性的最佳实践。

RDB 持久化和添加副本

为了通过 RDB 快照备份集群或向集群添加副本获得最佳结果,请遵循以下最佳实践:

内存管理

RDB 快照使用进程分叉和“写时复制”机制来创建节点数据的快照。根据对节点的写入模式,节点的已用内存会随着写入操作所涉及的页面被复制而增加。内存占用量最多可达到节点中数据大小的两倍。

为确保节点有足够的内存来完成快照,请将 maxmemory 保持或设置为节点容量的 80%,以便预留 20% 的容量用于开销。除了监控快照之外,此内存开销还有助于您管理工作负载,以成功创建快照。此外,在添加副本时,请尽可能降低写入流量。如需了解详情,请参阅监控具有高写入负载的集群。

过时快照

从过时快照恢复节点可能会导致应用出现性能问题,因为应用会尝试协调大量过时的密钥或对数据库的其他更改,例如架构更改。如果您担心从过时的快照中恢复,可以停用 RDB 持久性功能。重新启用持久性后,系统会在下一个预定的快照间隔拍摄快照。

RDB 快照对性能的影响

根据您的工作负载模式,RDB 快照可能会影响集群的性能,并会增加应用的延迟时间。如果您可以接受较低的快照频率,则可以将 RDB 快照安排在低集群流量期间运行,以最大限度地降低 RDB 快照的性能影响。

例如,如果您的集群在凌晨 1 点到凌晨 4 点之间的流量较低,则可以将开始时间设置为凌晨 3 点,并将时间间隔设置为 24 小时。

如果您的系统具有恒定负载,并且需要频繁的快照,您应仔细评估性能影响,并权衡将 RDB 快照用于工作负载的好处。

添加副本

添加副本需要 RDB 快照。如需详细了解 RDB 快照,请参阅内存管理。

何时使用单可用区集群

如果您将集群配置为不使用副本,则建议您使用单可用区集群。原因如下:

费用和性能

如果您的主要目标是最大限度地降低成本,并为位于同一区域的客户端提供最佳性能,那么我们建议您选择单可用区集群。

最大限度地降低服务中断的影响

选择单可用区集群时,可用区服务中断不太可能影响您的集群。通过将所有节点放置在单个可用区中,可用区级服务中断影响服务器的几率从 100% 降至 33%。集群所在的可用区发生故障的概率为 33%,而位于不可用可用区中的节点受到影响的概率为 100%。

快速恢复

如果单可用区集群发生可用区级服务中断,Memorystore for Redis Cluster 会简化数据恢复。您可以在正常运行的可用区中快速预配新集群,并重定向应用,以最大限度地减少运营中断。

容量规划最佳实践

为确保您能够成功预配资源并构建弹性架构,我们建议您遵循以下容量规划最佳实践:

  • 跨多个位置部署:如果您因临时资源限制而无法在首选可用区中创建集群,请尝试在同一区域内的其他可用区或在其他区域中创建集群。
  • 使用跨区域访问:将客户端配置为访问位于不同区域的集群。如果您因本地资源限制而需要预配位于其他区域的集群,则客户端可以连接到该集群。
  • 使用跨区域复制:如需将备用区域中的次要集群提升为主要读写集群以进行灾难恢复,请执行切换。

Lettuce 最佳实践

本部分介绍了使用 Lettuce 连接到集群的最佳实践。

更新参数值

使用 Lettuce 时,请将 validateClusterNodeMembership 参数更改为 false。否则,当拓扑发生变化时,您可能会收到 unknownPartition 错误。

启用传输层安全协议 (TLS)

本部分介绍了使用传输层安全协议 (TLS) 的安全优势和性能影响,以及启用该协议的建议。

安全优势

使用 TLS 可获得以下安全优势:

  • Identity and Access Management (IAM) 身份验证:TLS 使用此类型的身份验证来防范服务器欺骗攻击,例如中间人攻击。
  • 传输加密:Google Cloud的内置加密功能可在基础架构层级保护 Google 网络内的流量。不过,这需要同时信任 Google 的主机和网络栈。虽然此加密是透明的,并且默认处于启用状态,但它不是端到端加密。另一方面,TLS 在应用层使用传输中加密。这种端到端加密可让您更好地控制加密密钥和流程。
  • 身份验证令牌保护:如果您使用 IAM 身份验证,则启用 TLS 可最大限度地降低身份验证令牌泄露的风险。

性能影响

TLS 会通过以下方式影响性能:

  • 建立连接:已建立 TLS 会话的客户端和服务器可以恢复会话,而无需重复在客户端和服务器之间建立连接的资源密集型过程。通过启用 TLS 恢复,您可以减少在客户端和服务器之间建立连接的开销。

    如果您不建立 TLS 恢复,则建立连接会占用大量资源。对于新连接和现有连接,客户端和服务器之间的许多连接可能会导致连接超时。这可能会导致滚雪球效应,因为 Memorystore for Redis Cluster 会尝试重新建立超时连接,从而增加用于建立连接的资源。

  • 加密和解密数据:数据加密和解密涉及 CPU 密集型操作,会影响客户端和服务器。这可能会降低集群的容量并增加集群的延迟时间。

建议

在考虑是否启用 TLS 时,我们建议您评估安全政策,同时考虑 TLS 的优缺点。如果您选择启用 TLS,请注意以下事项:

  • 启用 TLS 恢复功能可减少建立连接的开销。只有初始连接才需要客户端和服务器之间的连接。但是,客户端集群大小的突然扩展可能会导致每个新客户端主机的初始完整握手造成短暂中断。
  • 虽然某些客户端库可能不提供启用 TLS 的内置控件,但您可以使用自定义代码将此功能集成到集群中。