本页面提供了如何以最优方式使用 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 秒,副本的目标/cluster/cpu/maximum_utilization值为 0.5 秒。 - 对于每个节点有两个或更多副本的集群,主实例的目标
/cluster/cpu/maximum_utilization值为 0.9 秒,每个副本的目标/cluster/cpu/maximum_utilization值为 0.5 秒。
如果该指标的值超出这些建议值,我们建议您扩容集群中的分片数量。如果集群的副本数少于五个,您还可以扩容副本数量,最多可扩容到五个副本。
如果集群的 CPU 利用率过高,或者集群的资源耗尽(例如,连接过多),则集群可能会出现异常行为,并且外部指标可能会缺失。
资源密集型 Redis 命令
我们强烈建议您避免使用资源密集型 Redis 命令。使用这些命令可能会导致以下性能问题:
- 延迟时间较长和客户端超时
- 因增加内存用量的命令而导致的内存压力
- 由于 Redis 主线程被阻塞,导致节点复制和同步期间数据丢失
- 健康检查、可观测性和复制资源不足
下表列出了资源密集型 Redis 命令的示例,并为您提供了资源高效的替代方案。
| 类别 | 资源密集型命令 | 资源高效的替代方案 |
|---|---|---|
| 针对整个键空间运行 | KEYS |
SCAN |
| 针对可变长度的键集运行 | LRANGE |
限制用于查询的范围的大小。 |
ZRANGE |
限制用于查询的范围的大小。 | |
HGETALL |
HSCAN |
|
SMEMBERS |
SSCAN |
|
| 阻止脚本运行 | EVAL |
确保脚本不会无限期运行。 |
EVALSHA |
确保脚本不会无限期运行。 | |
| 移除文件和链接 | DEL |
UNLINK |
| 发布和订阅 | PUBLISH |
SPUBLISH |
SUBSCRIBE |
SSUBSCRIBE |
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 快照使用进程 fork 和 “写入时复制”机制 来拍摄节点数据的快照。 根据写入节点的模式,随着写入触及的页面被复制,节点的已用内存会增加。内存占用量可能高达节点中数据大小的两倍。
为确保节点有足够的内存来完成快照,请将
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 的建议。
安全优势
使用 TLS 可获得以下安全优势:
- 身份和访问权限管理 (IAM) 身份验证: TLS 使用此类型的身份验证来防范服务器欺骗攻击, 例如中间人攻击。
- 传输加密: Google Cloud内置加密功能可在 基础架构级别保护 Google 网络内的流量。但是,这需要信任 Google 的主机和网络堆栈。虽然此加密是透明的并且默认处于启用状态,但它不是端到端的。另一方面,TLS 在应用层使用传输加密。这种端到端加密让您可以更好地控制加密密钥和流程。
- 身份验证令牌保护:如果您使用 IAM 身份验证,则启用 TLS 可以最大限度地降低身份验证令牌暴露和泄露 的风险。
性能影响
TLS 会通过以下方式影响性能:
建立连接: 已建立 TLS 会话的客户端和服务器可以恢复会话, 而无需重复执行在客户端和服务器之间建立连接的资源密集型过程。 通过启用 TLS 恢复,您可以减少在客户端和服务器之间建立连接的开销。
如果您不建立 TLS 恢复,则建立连接是资源密集型的。对于新连接和现有连接,客户端和服务器之间的许多连接都可能导致连接超时。这可能会产生滚雪球效应,因为 Memorystore for Redis Cluster 会尝试重新建立超时的连接,从而增加其用于建立连接的资源。
加密和解密数据: 数据加密和解密涉及 CPU 密集型操作,这些操作会影响 客户端和服务器。这可能会降低集群的容量并增加集群的延迟时间。
建议
在考虑是否启用 TLS 时,我们建议您在考虑 TLS 的优缺点时评估您的安全政策。如果您选择启用 TLS,请注意以下事项:
- 启用 TLS 恢复可以减少建立连接的开销。客户端和服务器之间的连接仅在初始连接时需要。但是,客户端集群大小的突然扩大可能会导致短暂中断,这是由每个新客户端主机的初始完整握手造成的。
- 虽然某些 客户端库 可能不 提供用于启用 TLS 的内置控件,但您可以使用自定义代码将 此功能集成到集群中。