为什么我发现自己的 ElastiCache 集群中的内存使用量过高或不断增加?

上次更新日期:2022 年 9 月 15 日

我发现自己的 Amazon ElastiCache 集群中的内存使用量过高或不断增加。如何确定 ElastiCache 集群节点上的内存使用量?

解决方法

为了确定集群及其节点的总体内存使用量,请查看这些 Redis 指标。这些指标在 Amazon CloudWatch 中针对集群内的每个节点发布:

  • BytesUsedForCache:Redis 为数据集、缓冲区等分配的总字节数。此指标源自 Redis 节点的 INFO 命令输出。使用此指标来确定集群的内存利用率。
  • FreeableMemory:此主机级别指标显示主机上的可用内存数量。当缓存数据或开销造成内存使用量增加时,可以看到 FreeableMemory 降低。FreeableMemory 降低表明主机上的可用内存减少。如果 FreeableMemory 太低,可能会发生交换。
  • DataBaseMemoryUsagePercentage:此指标来自 Redis INFO 命令输出。这是集群节点所用的内存百分比。在此指标达到阈值的 100% 后,Redis 将启动 Redis 最大内存驱逐策略

请记住,默认情况下 ElastiCache for Redis 为非数据使用(例如,故障转移和备份)预留最大内存的 25%。如果没有为非数据使用指定足够的预留内存,交换的机会就会升高。有关更多信息,请参阅管理预留内存

内存使用量突然过高的原因

  • 最近添加的键:添加新的键值对会导致内存使用量增加。在现有键上添加元素也会增加内存使用量。检查 SetTypeCmds 指标以确定节点上是否存在近期数据更改。此指标记录写入类型命令的总数,它源自 Redis commandstats 统计信息。
  • 缓冲区使用量增加:客户端通过网络连接到 Redis。如果客户端读取缓存的速度不够快,Redis 会将响应数据保存在称为客户端输出缓冲区的内存空间中。客户端可以继续从缓冲区空间读取。如果订阅的客户端读取速度不够快,Pub 和 Sub 客户端也是如此。
    如果网络带宽存在瓶颈,或者集群持续处于高负载状态,则缓冲区使用量可能会继续累积。这种累积会导致内存耗尽和性能下降。默认情况下,ElastiCache for Redis 不会限制输出缓冲区的增加,每个客户端都有自己的缓冲区。使用 client-list 命令检查缓冲区的使用情况。
  • 大量新连接:大量的新连接可能会增加内存使用量。所有新连接都会创建一个文件描述符,它需要消耗内存。大量新连接的总内存消耗可能很高,从而导致数据驱逐或 OOM 错误。查看 NewConnections 指标,以了解接受的新连接的总数。
  • 高交换使用率:当有可用内存时,缓存节点上会出现一些交换使用率是正常情况。但是,过多的交换使用率可能会导致性能问题。高交换通常发生在运行时承受内存压力的节点中,从而导致可释放的内存较少。使用 SwapUsage 指标监测主机上的交换。
  • 高内存碎片化:高内存碎片化表示操作系统中的内存管理效率低下。移除键时,Redis 可能无法释放内存。使用 MemoryFragmentationRatio 指标监测碎片率。如果您遇到碎片化问题,打开 activedefrag 参数以进行活动内存碎片整理。
  • 大键:数据大小较大或其中包含大量元素的键称为大键。即使 CurrItems 指标保持在较低水平,也可能会因大键的存在而出现内存使用率过高。要检测数据集中的大键,请使用 redis-cli --bigkeys 命令。

控制高内存使用量的最佳实践

  • 对键使用 TTL:您可以在键上指定过期 TTL。这样做可以在过期后移除键,而不必等到产生内存压力。这样可以防止不必要的键导致 Redis 混乱。少量驱逐不是问题,但大量的驱逐意味着您的节点在内存压力下运行。
  • 使用驱逐策略:当缓存内存开始填满时,Redis 会根据 maxmemory-policy 驱逐键以释放空间。默认 maxmemory-policy 策略设置为 volatile_lru。最佳做法是选择特定于您的工作负载需求的驱逐策略。
  • 分配预留内存:为了避免失效转移或备份期间出现问题,最佳做法是将非数据使用的 reserved_memory_percentage 设置为至少 25%。如果没有足够的预留内存来执行失效转移或备份,则会出现交换和性能问题。
  • 使用连接池:连接池有助于控制 Redis 客户端尝试的大量新连接。查看有关处理大量新连接的 AWS 最佳实践指南
  • 调整输出缓冲区大小限制:您可以调整输出缓冲区限制以控制缓冲区空间使用量。ElastiCache for Redis 参数组提供了多个参数,从 client-output-buffer-limit-* 开始,用于避免客户端输出缓冲区使用量的无限制地增加。请注意,这些参数没有建议的限制,因为每个工作负载都是唯一的。最佳做法是对您的工作负载进行基准测试,以便于您选择适当的值。
  • 考虑使用哈希映射:在 Redis 中,Redis 数据库的总内存占用量是线性的。与字段较少的单个哈希映射键相比,它使用更少的单个键占用更多的内存。哈希映射有助于处理包含大量键的数据结构。除了哈希映射之外,您还可以利用 ziplist 编码,与哈希表相比,它减少了内存占用。请注意,使用哈希映射可能会导致 Redis 引擎使用量高峰,因为这是一个复杂的命令,所需的 CPU 比 set 操作更多。
  • 扩展集群:有时在采取必要的预防措施后,您可能会遇到内存压力。如果发生这种情况,并且使用量由预期工作负载造成,请考虑执行适当的扩展以缓解内存瓶颈。
  • 设置内存使用量警报。 您可以使用 CloudWatch 警报在内存使用量超过预设阈值时启动警报。使用 BytesUsedForCacheDatabaseMemoryUsagePercentage 指标从 CloudWatch 控制台创建警报,以进行监控和扩展。