避免 ElastiCache Redis 上的交换

避免 ElastiCache Redis 上的交换

我们的 ElastiCache Redis 实例交换一直存在问题。亚马逊似乎有一些粗略的内部监控,它会注意到交换使用量激增,并简单地重新启动 ElastiCache 实例(从而丢失所有缓存项目)。以下是过去 14 天我们的 ElastiCache 实例上的 BytesUsedForCache(蓝线)和 SwapUsage(橙线)图表:

Redis ElastiCache BytesUsedForCache 和 Swap

您可以看到交换使用量不断增长的模式似乎会触发我们的 ElastiCache 实例的重新启动,从而导致我们丢失所有缓存项目(BytesUsedForCache 降至 0)。

我们的 ElastiCache 仪表板的“缓存事件”选项卡有相应的条目:

源 ID | 类型 | 日期 | 事件

cache-instance-id | cache-cluster | 2015 年 9 月 22 日星期二 07:34:47 GMT-400 | 缓存节点 0001 已重新启动

cache-instance-id | cache-cluster | 2015 年 9 月 22 日星期二 07:34:42 GMT-400 | 在节点 0001 上重新启动缓存引擎时出错

cache-instance-id | cache-cluster | 2015 年 9 月 20 日星期日 11:13:05 GMT-400 | 缓存节点 0001 已重新启动

cache-instance-id | cache-cluster | 2015 年 9 月 17 日星期四 22:59:50 GMT-400 | 缓存节点 0001 已重新启动

cache-instance-id | cache-cluster | 2015 年 9 月 16 日星期三 10:36:52 GMT-400 | 缓存节点 0001 已重新启动

cache-instance-id | cache-cluster | 2015 年 9 月 15 日星期二 05:02:35 GMT-400 | 缓存节点 0001 已重新启动

(剪辑早期条目)

亚马逊声称

交换使用情况——在正常使用中,Memcached 和 Redis 都不应该执行交换

我们的相关(非默认)设置:

  • 实例类型:cache.r3.2xlarge
  • maxmemory-policy:allkeys-lru(我们之前一直使用默认的 volatile-lru,没有太大区别)
  • maxmemory-samples:10
  • reserved-memory:2500000000
  • 检查实例上的 INFO 命令,我看到mem_fragmentation_ratio1.00 到 1.05 之间

我们联系了 AWS 支持,但没有得到太多有用的建议:他们建议将保留内存调得更高(默认值为 0,我们保留了 2.5 GB)。我们没有为此缓存实例设置复制或快照,因此我认为不应该发生 BGSAVE 并导致额外的内存使用。

cache.r3.2xlarge 的上限maxmemory是 62495129600 字节,虽然我们reserved-memory很快就达到了上限(减去我们的),但我觉得主机操作系统会感到压力,不得不在这里如此快速地使用这么多交换空间,这似乎很奇怪,除非亚马逊出于某种原因提高了操作系统交换空间设置。有什么想法会让我们为什么会在 ElastiCache/Redis 上造成如此多的交换空间使用,或者我们可以尝试的解决方法?

答案1

因为这里没有其他人有答案,所以我想分享唯一对我们有用的方法。首先,这些想法确实不是工作:

  • 更大的缓存实例类型:在比我们现在使用的 cache.r3.2xlarge 更小的实例上也遇到了同样的问题
  • 调整maxmemory-policy: volatile-lru 和 allkeys-lru 似乎都没有什么区别
  • 撞击maxmemory-samples
  • 撞击reserved-memory
  • 强制所有客户端设置过期时间,一般最多为 24 小时,少数调用者允许最多 7 天,但绝大多数调用者使用 1-6 小时的过期时间。

以下是最终确实有很大帮助的方法:每十二小时运行一次作业,运行扫描对所有键以COUNT10,000 个块 () 的形式进行分析。以下是同一实例的 BytesUsedForCache,仍然是一个 cache.r3.2xlarge 实例,使用量比以前更大,设置与以前相同:

缓存已用字节数

内存使用量的锯齿状下降与 cron 作业的时间相对应。在这两周内,我们的交换使用量最高达到约 45 MB(在重新启动之前最高达到约 5 GB)。并且 ElastiCache 中的“缓存事件”选项卡不再报告缓存重新启动事件。

是的,这看起来像是一个临时解决方案,用户不应该自己做,Redis 应该足够聪明,可以自行处理这种清理工作。那么为什么这样做有效呢?Redis 不会对过期的键进行太多或任何预先清理,而是依靠在 GET 过程中删除过期的密钥或者,如果 Redis 意识到内存已满,那么它将开始逐出每个新 SET 的键,但我的理论是,此时 Redis 已经陷入困境。

答案2

我知道这可能已经过时了,但我在 aws 文档中遇到过这个问题。

https://aws.amazon.com/elasticache/pricing/ 他们声明 r3.2xlarge 有 58.2gb 内存。

https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/ParameterGroups.Redis.html 他们说系统最大内存为 62GB(这是最大内存策略生效的时候),而且不能更改。看来,无论 AWS 中的 Redis 如何,我们都会进行交换。

相关内容