内存管理最佳做法

本页面介绍 Memcached 实例的预配内存配置,以及如何在需要时增加预配内存。本页面还介绍了有效管理 Memcached 实例的内存所需要了解的其他最佳做法。

Memorystore 会为您的实例添加额外的内存(您看不到这种额外添加的内存),以适应 Memcached 进程造成的开销。但是,根据您的具体工作负载,内存开销可能会超过我们为此目的预配的额外内存。

当内存使用量超过 Memorystore 系统总内存时,内存不足 (OOM) 条件可能会导致系统完全清空缓存数据,这可能会中断您的应用和业务。

以下部分概述了为 Memcached 实例配置 Memorystore 时应遵循的一般原则。此外,本部分还介绍了可用于监控内存的指标和提醒,并说明您可以采取的措施。

内存管理概念

实例容量

实例容量是您以 GiB 为单位预配的内存量,也是您要为之付费的内存量。缓存内存与实例容量不同,因为缓存内存并不是固定的。但在默认情况下,当您创建 Memcached 实例时,实例容量等于缓存内存量。

例如,如果您选择 5 GiB 的实例容量,则默认情况下,您的实例有 5 GiB 的空间来存储内容项。

缓存内存限制

缓存内存是指 Memcached 实例可用作缓存的内存总量。默认情况下,缓存内存量等于您的实例容量。但是,调整预留内存可减少缓存内存。如需了解详情,请参阅预留内存。缓存内存占满后,Memcached 会开始逐出缓存中存储的内容,以便为新的写入内容腾出空间。

请注意,查看缓存内存指标时,Memcached 节点报告的缓存内存仅包含内容项已经占用的空间。这意味着 Memcached 可能会低估总缓存内存用量。缓存可能会将更多内存分配为 Slab 中的碎片。

内存开销

内存开销是 Memcached 进程占用的内存。其中不包括存储在内存中以缓存的内容项。

内存开销根据活跃连接数、总内容项数和内容项大小进行扩缩。此外,从理论上来说,内存开销是无界限的,因此可无限增长。

为了满足内存开销,Memorystore 会向实例添加额外的内存。但是您不会看到我们添加的额外内存量。对于大多数工作负载,内存开销应该不会造成问题。

如果不进行任何配置,空 Memorystore for Memcached 节点的内存应如下图所示。

占位符

随着您的应用向缓存添加内容项,Memcached 会累积连接缓冲区和内部哈希表等进程的开销:

占位符

由于开销增长不受限,因此某些工作负载的一些开销会超出预留限制,如下所示:

占位符

当开销和内容项填满所有可用空间时,Memcached 会耗尽内存,并且该进程必定会由操作系统终止,从而导致缓存被完全清空:

占位符

您可能会注意到,内存开销超过了 Memorystore 默认为开销分配的额外空间(由较高的系统内存利用率值表示)。在这种情况下,您可以增加预留内存参数,从而给您的工作负载创建额外的开销。

预留内存

预留内存是一项 Memorystore 配置,可让您增加内存开销可以使用的空间量。

如需增加可用于内存开销的内存量,请增加预留内存,这会减少可用的缓存内存。如果实例因内存开销高而遇到内存压力,则应增加此额外空间。

2021 年 10 月 25 日之后创建的实例的默认预留内存百分比为 10%。可以通过在实例上手动更新配置来替换此值。减少实例上的预留内存可以显著增加 OOM 条件的可能性。

下图显示了通过增加预留内存为内存开销创建额外空间的实例:

占位符

一旦 Memcached 缓存达到这个降低的限额,就会开始逐出内容。

占位符

开始使用实例后,根据系统内存利用率指标,您可能需要增加实例上的预留内存,以支持您的峰值工作负载。

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

系统内存利用率

系统内存等于预配的实例容量,外加 Memorystore 为内存开销添加的额外空间量。

系统内存利用率指标会显示所有已用内存(已存储的内容项加上内存开销)的百分比。这是一个重要的监控指标,因为它可以为您显示您还差多少可以完全占满实例的可用系统内存。当系统内存利用率指标接近 100% 时,实例更有可能遇到 OOM 条件。为了确保实例有足够的内存来支持工作负载,请务必始终保留充足的系统内存。

对于尝试填满缓存并依靠 Memcached 逐出来管理存储哪些内容项的工作负载,您应该会看到更高的系统内存使用率,并且您可能希望预先增加预留内存,以确保有充足的空间来满足开销。

系统内存利用率提醒

您应该设置提醒,以便在系统内存利用率指标超过 90% 时通知您。如果系统内存利用率较高,则您应更密切地监控该系统内存利用率指标,如果该指标显著上升,您应考虑采取措施管理系统内存利用率。在系统内存利用率达到较高水平时采取措施很重要,因为这样做可让您有时间来缓解由 OOM 条件导致的缓存刷新。

逐出政策

Memcached 使用经过优化的 LRU 算法,以便在内容项填充到缓存内存后将其逐出。如需了解如何停用缓存逐出,请参阅配置 Memcached 实例

监控逐出可以显示 Memcached 因大小限制而移除的键数。此指标不含因 TTL 到期而移除的项。如果您看到大量逐出,则增加实例数量可能会增加缓存命中率。

如果未启用逐出,并且缓存已满,则 Memcached 服务器中的项设置可能会失败。

缓存命中率

您应该定期监控缓存命中率指标,以便了解 Memcached 实例中的键成功返回的键查询次数所占的百分比。一般来说,缓存命中率越高越好,因为这意味着您的缓存会为更多缓存请求返回结果。

在大幅更改配置(例如调整预留内存、调整关键 TTL 或扩缩实例)之前,您记下缓存命中率。然后,在修改实例后,再次检查缓存命中率,以查看更改对此指标的影响。

监控实例的内存使用量

以下指标可让您深入了解实例的内存用量。要了解如何查看指标并设置提醒,请参阅监控 Memcached 实例

指标 完整指标地址
缓存内存 memcache.googleapis.com/node/cache_memory
系统内存利用率 memcache.googleapis.com/node/memory/utilization
缓存命中率 memcache.googleapis.com/node/hit_ratio
逐出的密钥数 memcache.googleapis.com/node/eviction_count

管理系统内存用量

如果实例遇到内存压力或 OOM 错误,请按照以下步骤解决此问题:

  1. 验证 OOM 条件
  2. 增加实例上的预留内存
  3. 纵向扩充实例
  4. 为易失性键设置 TTL
  5. 手动删除实例上的密钥
  6. 如果您仍遇到内存不足问题,请与 Google Cloud Platform 支持团队联系。

验证 OOM 条件

当实例达到 OOM 条件时,第一个信号是实例重启。如需了解重启是否由 OOM 条件引起,请查看正常运行时间系统内存利用率 metrics

如果系统内存利用率在正常运行时间降至 0 之前已超过 90%,则表示实例重启可能是由 OOM 条件引起的。

增加预留内存

增加预留内存可以给内存开销腾出更多空间。您可通过降低实例的缓存内存上限来实现此目的。如果系统内存利用率指标超过 90%,则应增加预留内存。

如需了解如何调整预留内存配置,请参阅配置 Memcached 实例

增加“预留内存”会减少用于存储内容项的可用内存,因此也会更快地逐出内容项。这会降低实例的缓存命中率。如果停用了逐出,则系统不会逐出项目。

纵向扩充实例

按照扩缩 Memcached 实例中的说明来增加节点数。如果您的应用配置为跨节点将键分片,这种举措会增加应用可用的总内容项存储空间,并减少存储在各节点上的键的数量。

为易失性键设置 TTL

配置应用以设置 Memcached 中存储的键的 TTL。默认情况下,Memcached 会定期检查过期键并将其移除,从而释放服务器上的空间并防止进一步分配缓存内存。

手动删除实例上的键

在内存不足时,您应该考虑删除键。但是,由于开源 Memcached 不会释放之前已分配的内存,因此删除键只会降低进入 OOM 条件的可能性。降低此可能性的原因就是新写入会使用空内存。增加内存开销仍可能导致 OOM 条件,因为之前分配的内存专用于存储内容项,不能用于开销。