在使用 Redis (6.x) 作为内存存储的 GCP App Engine 应用程序中,将
maxmemory-policy
配置为 allkeys-lru
,我们会遇到内存不足错误。
此外,我们写入 Redis 的每个密钥的 TTL 均为 2 小时。尽管如此,内存使用量图仍在稳步增长(偶尔会出现低谷),直到达到最大内存。当发生这种情况时,LRU 策略似乎无法回收内存,并且对 Redis 的所有调用最终都会出现“内存不足”错误。
在我看来,使用 LRU 策略回收内存是缓存服务器的核心功能,我无法想象 Redis 会存在真正的 bug。那么我们还应该研究一些其他配置选项吗?在所有
maxmemory-policy options
中,allkeys-lru
似乎是最合适的,用作数据库访问缓存。
解释是,GCP Memorystore 分配固定的内存大小,例如 1GB,并且默认情况下它还将 Redis 的 maxmemory 设置为相同的大小。 但 Redis 处理限制的方法是超越它。引用文档(https://redis.io/docs/reference/eviction/)“我们不断地跨越内存限制的边界,通过超越它,然后通过驱逐键返回到限制之下“。但 GCP 没有给任何余地,所以跨越限制不是一个选择,所以它会失败并出现内存不足错误。
解决方案是始终在 Memorystore 配置上设置
maxmemory-percent=95
,这意味着 LRU 回收操作在达到最大值的 95%(而不是 100%)时触发。当然,适当的值可能是其他值,但初步猜测 95% 似乎没问题。
当项目使用 Redis 创建 Memorystore 时,这绝对应该是默认设置。