本页面提供了如何以最优方式使用 Memorystore for Valkey 的指导。本页面还指出了需要避免的潜在问题。
内存管理最佳做法
本部分介绍了管理实例内存的策略,以便 Memorystore for Valkey 高效地为您的应用提供服务。
内存管理概念
写入负载 - 您在 Valkey 实例中添加或更新键的数量和速度。写入负载可能介于正常和非常高之间,具体取决于您的 Valkey 使用情形和应用使用模式。
驱逐政策 - Memorystore for Valkey 使用
volatile-lru
驱逐政策。您可以使用 Valkey 命令(例如 EXPIRE 命令)为键设置驱逐。
监控写入负载正常的实例
查看 /instance/cpu/maximum_utilization
指标。如果 /instance/cpu/maximum_utilization
为 100% 或更低,则在您使用正常写入负载时,Valkey 实例的性能会很好。
不过,如果内存用量接近 100%,并且您预计数据用量会增加,则应扩大实例大小,以便为新数据腾出空间。
监控写入负载较高的实例
查看 /instance/memory/maximum_utilization
指标。根据写入负载过高的情况的严重程度,您的实例可能会在达到以下阈值时出现性能问题:
如果
/instance/memory/maximum_utilization
达到 65% 或更高,写入负载可能会非常高,从而导致问题。如果
/instance/memory/maximum_utilization
达到 85% 或更高,写入负载可能会出现问题。
在这些情况下,您应扩大实例大小以提高性能。
如果您遇到问题,或者担心实例的写入负载较高,请与 Google Cloud 支持团队联系。
扩缩分片
在实例中扩缩分片数量时,您应在写入负载较低的期间进行扩缩。在高写入负载期间进行扩缩可能会因复制或槽迁移造成内存开销而导致实例的内存不足。
如果您的 Valkey 使用情形使用了键驱逐,则缩减实例大小可能会降低缓存命中率。不过,在这种情况下,您无需担心丢失数据,因为这是预期行为。
对于不希望丢失密钥的 Valkey 用例,您应仅缩减到仍有足够空间存储数据的较小实例。新的目标分片数量应至少为数据使用的内存的 1.5 倍。换句话说,您应预配足够的碎片,以容纳实例中当前数据量的 1.5 倍。您可以使用 /instance/memory/total_used_memory
指标查看实例中存储的数据量。
CPU 使用率最佳实践
如果发生意外的可用区中断,由于不可用可用区中的节点失去容量,您的实例的 CPU 资源也会减少。我们建议您使用高可用实例。每个分片使用两个副本(而不是每个分片一个副本)可在发生中断时提供额外的 CPU 资源。此外,我们建议您管理节点 CPU 使用率,以便在发生意外可用区停机时,节点有足够的 CPU 开销来处理因容量损失而产生的额外流量。您应使用主线程 CPU 秒数 /instance/cpu/maximum_utilization
指标监控主副本和副本的 CPU 使用情况。
根据您为每个节点预配的副本数量,我们建议您设置以下 /instance/cpu/maximum_utilization
CPU 使用率目标:
- 对于每个节点有 1 个副本的实例,您应将主副本和副本的
/instance/cpu/maximum_utilization
值设为 0.5 秒。 - 对于每个节点有 2 个副本的实例,您应将主副本的
/instance/cpu/maximum_utilization
值设为 0.9 秒,将副本的/instance/cpu/maximum_utilization
值设为 0.5 秒。
如果该指标的值超出这些建议,我们建议您扩容实例中的分片或副本数量。
CPU 开销较大的 Valkey 命令
您应避免运行因各种原因而费用高昂的 Valkey 命令。本部分列举了导致某些命令开销较高的一些原因,但并非详尽无遗。
对整个键空间执行操作的命令
- KEYS
对可变长度键集执行操作的命令
- LRANGE
- ZRANGE
- HGETALL
在脚本执行时阻塞的命令
- EVAL
- EVALSHA
使用开销大的命令的风险
- 延迟时间长且客户端超时。
- 由增加内存用量的命令导致的内存压力。
- 由于阻塞 Valkey 主线程,导致节点复制和同步期间数据丢失。
- 健康检查、可观测性和复制功能耗尽资源。
Valkey 客户端最佳实践
在连接到 Memorystore for Valkey 实例时,您的应用必须使用集群感知型 Valkey 客户端。如需查看集群感知型客户端和示例配置的示例,请参阅客户端库代码示例。您的客户端必须维护一个将哈希槽映射到实例中相应节点的映射,以便将请求发送到正确的节点,并避免因重定向而导致的性能开销。
客户端映射
在以下情况下,客户端必须获取槽和映射节点的完整列表:
在客户端初始化时,它必须填充初始槽到节点的映射。
从服务器收到
MOVED
重定向时,例如在故障切换的情况下,副本接管了之前主节点提供的所有槽,或者在将槽从来源主节点移至目标主节点时重新分片。从服务器收到
CLUSTERDOWN
错误,或与特定服务器的连接持续超时。从服务器收到
READONLY
错误时。当主副本降级为副本时,就可能会发生这种情况。此外,客户端应定期刷新拓扑,以便客户端为任何更改做好准备,并了解可能不会导致服务器重定向/出错的更改,例如添加新的副本节点。请注意,在拓扑刷新过程中,还应关闭所有过时连接,以减少在命令运行期间处理失败连接的需要。
客户端发现
通常,客户端发现是通过向 Valkey 服务器发出 SLOTS
、NODES
或 CLUSTER SHARDS
命令来完成的。我们建议使用 CLUSTER SHARDS
命令。CLUSTER SHARDS
通过提供更高效且可扩展的实例表示法,取代了 SLOTS
命令(已废弃)。
客户端发现命令的响应大小可能会因实例大小和拓扑而异。节点越多的大型实例生成的响应越大。因此,请务必确保执行节点拓扑发现的客户端数量不会无限增长。
这些节点拓扑刷新在 Valkey 服务器上非常耗费资源,但对应用可用性也至关重要。因此,请务必确保每个客户端在任何给定时间都发出单个发现请求(并将结果缓存在内存中),并且发出请求的客户端数量保持在一定范围内,以免服务器过载。
例如,当客户端应用启动或与服务器断开连接且必须执行节点发现时,一个常见错误是客户端应用会发出多次重新连接和发现请求,但在重试时未添加指数退避。这可能会导致 Valkey 服务器长时间无响应,从而导致 CPU 利用率非常高。
避免在 Valkey 上发现过载
为了缓解连接和发现请求突然激增所带来的影响,我们建议您采取以下措施:
实现大小有限且较小的客户端连接池,以限制来自客户端应用的并发传入连接数量。
当客户端因超时而与服务器断开连接时,请使用带抖动的指数退避算法进行重试。这有助于避免多个客户端同时使服务器过载。
使用 Memorystore for Valkey 发现端点执行节点发现。发现端点具有高可用性,并在实例中的所有节点之间进行负载均衡。此外,发现端点会尝试将节点发现请求路由到具有最新拓扑视图的节点。
持久性最佳实践
本部分介绍了持久化方面的最佳实践。
RDB 持久化
为了通过 RDB 快照备份实例获得最佳结果,您应遵循以下最佳实践:
内存管理
RDB 快照使用进程分叉和“写时复制”机制来获取节点数据的快照。随着写入所涉及页面的复制,节点的已用内存会随之增长,具体取决于写入节点的模式。在最糟糕的情况下,内存占用量可能会是节点中数据大小的两倍。
为确保节点有足够的内存来完成快照,您应将 maxmemory
保持或设为节点容量的 80%,以便将 20% 的容量预留给开销。如需了解详情,请参阅监控写入负载较高的实例。除了监控快照之外,这种内存开销还有助于您管理工作负载,以便成功创建快照。
过时快照
从过时快照恢复节点可能会导致应用出现性能问题,因为应用会尝试协调大量过时的密钥或对数据库的其他更改,例如架构更改。如果您担心从过时快照恢复,可以停用 RDB 持久性功能。重新启用永久性存储后,系统会在下次按计划创建快照的时间间隔创建快照。
RDB 快照对性能的影响
根据您的工作负载模式,RDB 快照可能会影响实例的性能,并会增加应用的延迟时间。如果您不介意快照的频率较低,可以将 RDB 快照安排在低实例流量期间运行,以最大限度地降低 RDB 快照的性能影响。
例如,如果您的实例在凌晨 1 点到凌晨 4 点的流量较低,则可以将开始时间设置为凌晨 3 点,并将时间间隔设置为 24 小时。
如果您的系统具有恒定负载,并且需要频繁的快照,您应仔细评估性能影响,并权衡将 RDB 快照用于工作负载的好处。
如果您的实例不使用副本,请选择单可用区实例
在配置没有副本的实例时,我们建议采用单可用区架构,以提高可靠性。原因如下:
最大限度地减少停机影响
可用区级服务中断不太可能影响您的实例。将所有节点放置在单个可用区内,可用区服务中断对服务器造成影响的几率从 100% 降至 33%。这是因为实例所在的可用区发生故障的概率为 33%,而位于不可用可用区的节点受到影响的概率为 100%。
快速恢复
如果发生可用区级服务中断,系统会简化恢复流程。您可以通过在正常运行的可用区中快速预配新实例并重定向应用来响应,从而最大限度地减少操作中断。