Memorystore for Redis Cluster 最佳实践

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

内存管理最佳做法

本部分介绍了管理实例内存的策略,以便 Memorystore for Redis 集群能够高效地为您的应用提供服务。

内存管理概念

  • 写入负载 - 在 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 支持团队联系。

扩缩分片

当您扩缩实例中的分片数量时,应在写入负载较低的期间进行扩缩。在高写入负载期间进行扩缩可能会因复制或 slot 迁移造成内存开销而导致实例的内存不足。

如果您的 Redis 使用场景涉及密钥逐出,则缩减集群规模可能会降低缓存命中率。不过,在这种情况下,您无需担心数据丢失,因为密钥逐出是预期行为。

对于不想丢失密钥的 Redis 用例,您应仅缩减到仍有足够空间来存储数据的较小集群。新的目标分片数应至少为数据所用内存的 1.5 倍。换句话说,您应预配足够的分片,以满足当前集群中 1.5 倍的数据量。您可以使用 /cluster/memory/total_used_memory 指标来查看实例中存储的数据量。

CPU 使用率最佳实践

如果发生意外的可用区级中断,由于不可用可用区中的节点丢失了容量,这会导致集群的 CPU 资源减少。我们建议使用高可用性集群。每个分片使用两个副本(而不是每个分片使用一个副本)可在中断期间提供额外的 CPU 资源。此外,我们建议您管理节点 CPU 使用率,以便节点有足够的 CPU 开销来处理因意外的可用区中断而导致的容量损失所带来的额外流量。您应使用 /cluster/cpu/maximum_utilization 指标监控主数据库和副本的 CPU 使用情况。

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

  • 对于每个节点有一个副本的实例,当副本被指定为读取副本时,主实例和副本的目标 /cluster/cpu/maximum_utilization 值均为 0.5 秒。
  • 对于每个节点有两个副本的实例,主副本的目标 /cluster/cpu/maximum_utilization 值为 0.8 秒,每个副本的目标 /cluster/cpu/maximum_utilization 值为 0.5 秒。

如果该指标的值超过这些建议值,我们建议您扩容实例中的分片或副本数量。

资源密集型 Redis 命令

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

  • 延迟时间较长和客户端超时
  • 因增加内存用量的命令而导致的内存压力
  • 节点复制和同步期间因 Redis 主线程被阻塞而导致的数据丢失
  • 健康检查、可观测性和复制资源不足

下表列出了资源消耗型 Redis 命令的示例,并提供了资源节约型替代方案。

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

Redis 客户端最佳实践

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

客户端映射

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

  • 当客户端初始化时,它必须填充初始 slot 到节点映射。

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

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

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

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

客户端发现

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

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

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

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

避免 Redis 上的发现过载

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

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

  • 当客户端因超时而与服务器断开连接时,使用抖动指数退避算法重试。这有助于避免多个客户端同时使服务器过载。

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

持久性最佳实践

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

RDB 持久性和添加副本

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

内存管理

RDB 快照使用进程派生和写入时复制机制来拍摄节点数据快照。根据对节点的写入模式,随着写入所触及的页面被复制,节点的已用内存会不断增长。内存占用空间最多可达到节点中数据大小的两倍。

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

过时的快照

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

RDB 快照的性能影响

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

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

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

添加副本

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

如果您的实例不使用副本,请选择单可用区实例

在配置没有副本的实例时,我们建议采用单可用区架构,以提高可靠性。原因如下:

尽量减少中断的影响

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

快速恢复

如果发生可用区级服务中断,恢复流程会更加顺畅。您可以快速在正常运行的可用区中预配新实例,并重定向应用,以尽可能减少中断。

生菜最佳实践

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

更新参数值

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