内存管理最佳做法

未正确管理和配置的 Memorystore for Redis 实例可能会遇到内存压力,从而可能会影响应用性能。本页面介绍了可用于高效地管理实例内存用量的最佳做法。

在本主题中

内存管理概念

本部分介绍了为管理实例的内存用量而需要了解的概念。

实例容量

  • 实例容量是您预配的内存量以及您需要支付费用的内存量(以 GB 为单位)。如需详细了解如何选择合适的实例容量,请参阅调整 Memorystore 实例的大小

最大内存配置

  • 最大内存是一项 Redis 配置,可让您设置逐出政策生效的内存限制。Memorystore for Redis 将此配置指定为 maxmemory-gb。创建实例时,maxmemory-gb 设置为实例容量。根据系统内存使用率指标,您可能需要降低 maxmemory-gb 限制才能提供适用于工作负载峰值的内存开销。

    如需了解详情,请参阅管理系统内存使用率

    如需了解如何调整 maxmemory-gb,请参阅配置 Redis 实例

系统内存使用率

  • 通过系统内存使用率指标,您可以相对于系统内存来衡量实例的内存用量。系统内存由 Memorystore 自动管理,以处理由内存密集型操作和开源 Redis 中常见的内存碎片化导致的内存用量峰值。

    如果系统内存使用率指标超过 80%,则表示实例的内存不足,您应按照管理系统内存使用率中的说明进行操作。如果您未采取任何措施,但内存用量继续增加,则可能会因内存不足而导致实例崩溃。由于发生内存碎片化,您的系统内存使用率指标可能会超过 80%。或者,如果该指标迅速上升到 80% 或更高,表示您可能使用了某项内存密集型操作

已用内存

  • 已用内存指标显示 Memorystore 实例中的数据量。实例的已用内存可增长到 maxmemory-gb 配置限制。当已用内存超出 maxmemory-gb 限制时,逐出政策就会生效。

逐出政策

  • 当实例数据达到 maxmemory-gb 限制时,实例的逐出政策(也称为最大内存政策)决定了 Redis 如何逐出键。Redis 根据正常缓存使用场景逐出键。键逐出是一个后台进程,因此不会在达到 maxmemory-gb 限制后立即逐出键。高写入速率可能会超过键逐出速率,从而导致内存不足的情况。

    Memorystore 实例的默认逐出政策为 volatile-lru。如果您使用的是 volatile-* 逐出政策,请务必为您希望到期的键设置 TTL,否则 Redis 将没有需要逐出的键。

    如需查看逐出政策的列表,请参阅最大内存政策

    如需了解如何更改逐出政策,请参阅配置 Redis 实例

内存碎片化

  • 即使已用内存占 maxmemory-gb 的比率较低,内存碎片化也可能导致您的 Memorystore 实例内存不足。当操作系统分配内存页面(Redis 在重复进行写入和删除操作后无法充分利用这些页面)时,就会发生内存碎片化。此类页面的积累可能会导致系统内存不足,并最终导致 Redis 服务器崩溃。activedefrag Redis 配置可以帮助减少碎片化。

主动碎片整理

  • Redis 4.0 及更高版本提供 activedefrag 配置。如有可能,您应该使用 Redis 4.0 创建 Memorystore 实例。Memorystore 默认将 activedefrag 设置为“no”。将 activedefrag 设置为“yes”会导致 CPU 权衡取舍,但可以帮助缓解会导致内存不足问题的内存碎片化问题。

    如果系统内存使用率指标指示内存碎片化,则应启用 activedefrag。否则,activedefrag 仍为可选设置。

内存密集型操作

以下操作会占用大量内存,尤其是在运行时结合了高写入速率:

导出操作

Memorystore 导出功能使用 Redis BGSAVE 操作,该操作会使用“写入时复制”。导出所需的内存可能是数据所占用空间大小的两倍,具体因数据的大小、写入量以及所按的键而异。因此,要使导出成功,您可能需要在导出期间将 maxmemory-gb 限制降低到f实例容量的 50%。

标准层级实例的扩缩和版本升级操作

在高写入负载期间进行扩缩升级可能会因复制造成内存开销而导致实例的内存不足。如果扩缩或升级操作因内存不足而失败,您应该:

  • 在扩缩/升级操作之前,将 maxmemory-gb 减少到实例容量的 50%。如有可能,您还应该在实例流量较低时降低最大内存,因为这样做可以降低因最大内存降低而对缓存命中率造成的负面影响。
  • 在低写入负载期间进行扩缩/升级。

监控实例的内存用量

如本部分中所述监控指标并设置提醒。这些指标和提醒可让您深入了解实例的内存用量。如需了解如何查看指标和设置提醒,请参阅监控 Redis 实例

指标 完整指标地址
最大内存 redis.googleapis.com/stats/memory/maxmemory
内存用量 redis.googleapis.com/stats/memory/usage
内存使用率 redis.googleapis.com/stats/memory/usage_ratio
系统内存过载时长 redis.googleapis.com/stats/memory/system_memory_overload_duration
系统内存使用率 redis.googleapis.com/stats/memory/system_memory_usage_ratio
缓存命中率 redis.googleapis.com/stats/memory/cache_hit_ratio
可过期键 redis.googleapis.com/keyspace/keys_with_expiration
过期的键 redis.googleapis.com/stats/expired_keys
逐出的键 redis.googleapis.com/stats/evicted_keys

内存使用率

内存使用率指标表示工作集大小与 maxmemory-gb 限制的接近程度。除非将逐出政策设为不逐出,否则达到最大内存的实例数据并不一定表示存在问题。但是,键逐出是需要花费时间处理的后台进程。如果您的写入速率较高,则您可能会在 Redis 有时间逐出键以释放空间之前用尽内存。

系统内存使用率

系统内存使用率是需要监控的关键指标。为了确保实例有足够的内存来支持工作负载和其他内存密集型操作,请务必始终保留足够的系统内存。

设置提醒以便在系统内存使用率指标达到 80% 时通知您。如果该指标达到 80%,您应该开始更密切地监控系统内存使用率指标。如果系统内存使用率持续大幅增长,您应该开启主动碎片整理、降低最大内存并考虑扩缩实例。

一旦系统内存使用率达到 100%,任何进一步增加实例内存占用量的操作都会被阻止,并且 Redis 将返回以下错误:

-OOM command not allowed under OOM prevention.

如需了解详情,请参阅管理系统内存使用率

系统内存过载时长

如果内存用量过高,则 Memorystore 会阻止对实例的写入,以确保实例运行状况良好。系统内存过载时长会跟踪实例处于已被阻止写入状态的时长。

您应该为此指标设置提醒,以便了解何时阻止对实例进行写入。此外,您还可以参考此指标来排查收到的 -OOM command not allowed under OOM prevention. 错误。

缓存命中率

您应该定期监控缓存命中率,以便了解 Redis 实例中的键成功返回的键查找的百分比。一般而言,较高的缓存命中率要好于较低的缓存命中率。在大幅更改配置(例如调整 maxmemory-gb 限制、更改逐出政策或扩缩实例)之前,您应记下缓存命中率。然后,在修改实例后,再次检查缓存命中率,以查看更改对此指标的影响。

可过期键和过期键

Stackdriver 指标可过期键会监控设置为要过期的键的数量。如果没有可过期的键,可能表示您没有为键设置 TTL。在这种情况下,当您的实例数据达到 maxmemory-gb 限制时,没有任何要逐出的键,因此不会导致内存不足的情况。

您可以监控的另一个指标是过期键。如果指标显示有许多过期键,但您的实例仍然遇到内存压力,则应降低 maxmemory-gb

解决内存不足的情况

如果您的实例遇到内存压力或内存不足的情况,请遵循以下最佳做法。

  1. 如果使用的是 volatile-* 逐出政策,请务必为希望到期的键设置 TTL。如需了解详情,请参阅逐出政策

  2. 对于运行 Redis 4.0 及更高版本的实例:

    1. 为您的实例启用 activedefrag。如需了解详情,请参阅主动碎片整理
  3. 了解如何使用指标来解决内存不足问题,并深入了解实例的内存用量:监控实例的内存用量管理系统内存使用率

  4. 了解如何在运行内存密集型操作时调整最大内存。

  5. 如果系统内存使用率指标超过 80%,请降低实例的 maxmemory-gb 限制。如需了解详情,请参阅管理系统内存使用率

  6. 请考虑扩充实例容量。

  7. 如果您仍遇到内存不足问题,请与 Google Cloud Platform 支持团队联系。

调整 Memorystore 实例的大小

本部分介绍了三种不同的方法,可帮助您根据工作负载调整实例的大小:

确定 Memorystore 实例的初始大小

首先,您应该选择想要标准层级实例还是基本层级实例。如需详细了解 Memorystore for Redis 层级,请参阅 Redis 层级功能。 为应用选择合适的层级后,请按照以下步骤确定您需要的实例大小:

  1. 确定数据的大小。

    • 估算应用将向 Redis 实例写入的键的数量和平均大小。将使用这些值相乘以粗略估算所需的实例大小。
  2. 选择一项逐出政策。

    • 如果您使用 noeviction 最大内存政策,则实例大小必须足以容纳峰值工作负载和工作集。如果您在使用此最大内存政策时导致内存不足,则您的实例可能遇到内存不足的情况。
    • 其他逐出政策不会影响您应预配的实例大小。
  3. 为标准层级实例预配额外的内存

    • 与基本层级实例不同,标准层级实例保留 10% 的实例容量作为复制缓冲区。如果您选择标准层级实例,请务必从第 1 步开始估算数据,并为复制缓冲区额外预配 10% 的容量。
  4. 估算您的平均写入速率和峰值写入速率

    • 如有可能,请估算应用将要使用的写入速率和键大小。与键移除速率相比,写入速率决定了实例随时间的增长速度。
  5. 扩允以达到所需的缓存命中率

    • 监控缓存命中率,如果您未获得所需数量的成功缓存命中,则表示您需要增加实例大小,或确保应用将所请求但尚未实现的键写入 Memorystore 实例。

确定实例是否因内存不足而阻止写入

如果遇到以下错误:

-OOM command not allowed under OOM prevention.

则检查是否出现以下情况:

  1. 在实例开始遇到问题之前,系统内存使用率指标已超过 80%。
  2. 在实例出现问题之前,系统内存使用率快速上升。
  3. 在您遇到写入被阻止的同一时间段内,系统内存过载时长指标显示的值大于零。

在这种情况下,这可能表示实例因内存不足而阻止写入。

管理系统内存使用率

设置提醒以便在系统内存使用率指标超出 80% 时通知您。如果系统内存使用率超过 80%,应采取适当的措施,让实例不会耗尽内存。根据写入卷和键访问模式,系统内存使用率可能会迅速增长到 100%。Memorystore 提供以下方法来管理系统内存使用率

  • 为运行 Redis 4.0 及更高版本的实例启用 activedefrag
  • 降低实例的 maxmemory-gb 限制。
  • 扩充实例。
  • 选择适当的逐出政策。
  • 为易失性键设置 TTL。
  • 从实例中手动删除键。

开启主动碎片整理

如果系统内存使用率超过 80%,请开启 activedefrag(适用于运行 Redis 4.0 和更高版本的实例)。碎片整理可能需要数小时才能释放碎片化内存。如果写入流量较高,则仅进行碎片整理可能不足以阻止实例用尽内存。因此,您可能需要实施以下建议:

降低实例的最大内存限制

如果系统内存使用率超过 80%,则应降低 maxmemory-gb,但请先查看系统内存使用率随时间变化的情况,以确定要设置的新 maxmemory-gb 限制。

场景 1:系统内存使用率逐渐缓慢上升。这可能是碎片化导致的问题,您应该以较小的增量降低 maxmemory-gb,直到系统内存使用率低于 80%。

场景 2:系统内存使用率快速上升,您的实例上出现明显的写入负载。内存密集型操作可能导致出现峰值。在这种情况下,您应该以较大的增量降低 maxmemory-gb 限制,以确保避免实例进入内存不足状况,或从内存不足的情况中恢复。请注意,降低最大内存可能会降低实例的缓存命中率。缓存命中率非常低表示您应该扩充实例,以便应用可以从使用 Redis 的优势中获利。如需了解如何调整 maxmemory-gb 配置,请参阅配置 Redis 实例

扩充实例

按照扩缩 Redis 实例中的说明来增加实例容量。

最大内存扩缩示例:

如果您有一个 10 GB 的实例,并将 maxmemory-gb 设置为 8 GB,则您有 8 GB 用于存储键,且有 2 GB 的内存开销。如果您将实例扩缩为 20 GB,则 maxmemory-gb 会扩缩为 16 GB。因此,您的实例现在有 16 GB 的内存可用于存储键,且有 4 GB 的内存开销。如需了解如何增加或减小实例的大小,请参阅扩缩 Redis 实例

选择适当的逐出政策

如果您要存储易失性数据,请选择一项 volatile-* 逐出政策。如果您要存储非易失性数据,请选择一项 allkeys-* 政策。

从实例中手动删除键

您可以通过从实例中手动删除键来改善内存不足的情况。这是一个临时解决方案,可帮助您改善实例运行状况。