避免交换ElastiCache Redis

我们一直在ElastiCache Redis实例交换中遇到麻烦。 亚马逊似乎有一些粗暴的内部监控,注意到交换使用率高峰,只是重新启动ElastiCache实例(从而失去了我们所有的caching项目)。 以下是过去14天ElastiCache实例上的BytesUsedForCache(蓝线)和SwapUsage(橙线)的图表:

Redis ElastiCache BytesUsedForCache和Swap

您可以看到越来越多的交换使用的模式似乎触发我们的ElastiCache实例重启,其中我们失去了所有的caching项目(BytesUsedForCache下降到0)。

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

来源ID | types| date| 事件

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

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

cache-instance-id | cache-cluster | Sun Sep 20 11:13:05 GMT-400 2015 | caching节点0001重新启动

cache-instance-id | cache-cluster | Thu Sep 17 22:59:50 GMT-400 2015 | caching节点0001重新启动

cache-instance-id | cache-cluster | Wed Sep 16 10:36:52 GMT-400 2015 | caching节点0001重新启动

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

(剪下较早的条目)

亚马逊声称 :

SwapUsage – 在正常使用情况下,Memcached和Redis都不应该执行交换

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

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

我们已经联系了AWS的支持,并没有得到太多有用的build议:他们build议启动保留内存甚至更高(默认值为0,我们保留了2.5 GB)。 我们没有为此caching实例设置复制或快照,所以我认为不应该发生BGSAVE,并导致额外的内存使用

maxmemory上限是62495129600个字节,虽然我们很快就达到了上限(减去我们的reserved-memory ),但是我觉得主机操作系统在这里使用这么多swap会感到压力,所以很快,除非亚马逊已经由于某种原因引起了操作系统swappiness设置。 任何想法为什么我们会在ElastiCache / Redis上造成太多的交换使用,或者我们可能会尝试的解决方法?

既然没有其他人在这里回答,我以为我会分享唯一为我们工作的东西。 首先,这些想法不起作用:

  • 较大的caching实例types:在比我们现在使用的cache.r3.2xlarge更小的实例上有相同的问题
  • 调整maxmemory-policy :volatile-lru和allkeys-lru都没有任何区别
  • 碰到maxmemory-samples
  • 碰撞reserved-memory
  • 迫使所有的客户设置到期时间,通常最多24小时,less数罕见的呼叫者允许长达7天,但绝大多数呼叫者使用1-6小时的到期时间。

以下是最后的帮助,很多:运行一个工作每十二小时运行一个SCAN扫描所有密钥( COUNT )为10,000。 这是同一个实例的BytesUsedForCache,在比以前更重用的情况下,仍然是一个cache.r3.2xlarge实例,使用与之前相同的设置:

BytesUsedForCache

内存使用中的锯齿下降对应于cron作业的次数。 在这两周的时间里,我们的交换使用已经超过了〜45MB(在重启之前,最高可达5GB)。 ElastiCache中的caching事件选项卡不报告caching重新启动事件。

是的,这似乎是用户不应该自己做的一个混乱,而且Redis应该足够聪明来处理这个清理工作。 那么为什么这个工作? 那么,Redis并没有做太多或任何先发制人的清理过期的密钥,而是依靠在GET期间驱逐过期的密钥 。 或者,如果Redis意识到内存已满,那么它将开始为每个新SET设置驱逐键,但是我的理论是,在这一点上,Redis已经被解决了。