选择有效Redis逐出策略指南

选择与您的缓存、会话或混合工作负载匹配的Redis逐出策略,并调整maxmemory而不丢失关键键。

选择有效Redis逐出策略指南

Redis之所以快速,是因为它将数据保存在内存中,但内存是有限的。当您的Redis实例达到maxmemory时,逐出策略决定Redis是删除键、拒绝写入,还是仅逐出具有过期时间的键。

当Redis充当缓存、会话存储或混合用途数据存储时,选择有效的Redis逐出策略最为重要。错误的策略可能会逐出重要键,或在流量高峰期间导致写入失败。


理解Redis逐出和maxmemory

只有当Redis内存使用超过maxmemory配置指令设置的限制时,逐出策略才会生效。如果未设置maxmemory或设置为0,Redis不会对正常写入应用内存限制。在专用主机上,这最终可能导致操作系统内存压力,因此生产缓存部署通常会设置明确限制。

要启用逐出,您必须在redis.conf文件中或通过CONFIG SET命令配置maxmemory

# 将maxmemory设置为2GB
CONFIG SET maxmemory 2gb

一旦内存受限,当写入命令需要更多内存时,Redis使用配置的逐出策略来决定丢弃哪些键。

内置的Redis逐出策略

Redis提供几种不同的策略。这些策略通过maxmemory-policy指令配置。策略通常分为两类:基于**最近最少使用(LRU)最不经常使用(LFU)的策略,以及针对设置了生存时间(TTL)**的键的策略。

1. 无需TTL的策略

这些策略对数据库中的所有键进行操作,无论它们是否设置了过期时间。

noeviction

这是默认策略。当达到内存限制时,Redis拒绝写入命令(如SETLPUSH等),并向客户端返回错误。读取(GET)仍然允许。这通常适用于数据丢失不可接受的关键任务数据,但在高写入压力下可能导致应用程序错误。

allkeys-lru

逐出数据库中所有键中最近最少使用的键,直到内存使用低于maxmemory限制。这是通用缓存的标配选择,其中所有数据项都可同等缓存。

allkeys-lfu

逐出所有键中最不经常使用的键。LFU优先保留经常访问的键,即使它们最近没有被访问。这在访问模式波动时有效,但非常受欢迎的项目可能会无限期驻留。

allkeys-random

随机选择键进行逐出,直到满足内存限制。除非数据访问模式完全均匀且不可预测,否则很少推荐用于生产缓存。

2. 需要TTL(易失键)的策略

这些策略仅考虑设置了明确过期时间(EXPIRESETEX)的键。在执行逐出时,它们忽略不过期的键。

volatile-lru

逐出设置了过期时间的键中最近最少使用的键。

volatile-lfu

逐出设置了过期时间的键中最不经常使用的键。

volatile-random

随机逐出设置了过期时间的键中的一个键。

volatile-ttl

首先逐出剩余生存时间(TTL)最短的键。这适用于时间敏感数据,如会话令牌或临时应用程序状态,确保先清理较旧、即将过期的数据。


为工作负载选择正确的策略

最佳的逐出策略完全取决于您缓存什么以及您的应用程序如何使用数据。

工作负载类型 推荐策略 理由
通用缓存(最常见) allkeys-lru 假设较旧、未使用的数据应首先删除,无论TTL如何。简单且高效。
时间敏感数据(例如,令牌、短期会话) volatile-ttl 优先逐出剩余TTL最短的键。
热数据缓存(高访问倾斜) allkeys-lfuvolatile-lfu 保护频繁访问的项目不被因近期不活动而逐出。
强制数据保留(不允许丢失) noeviction 通过写入错误防止数据丢失,需要手动干预或上游应用程序处理。
混合工作负载(部分数据过期,部分不过期) volatile-lruvolatile-lfuvolatile-ttl 如果您的不过期键至关重要,使用易失策略通过仅逐出明确过期的键来保护它们。

实际示例:实现会话存储

如果Redis主要用于存储用户会话,为每个会话键设置明确的TTL,例如30分钟。当剩余生存时间是最重要的信号时,volatile-ttl可以工作。如果您的应用程序在活动时刷新会话TTL,活动会话自然会保持更长的剩余TTL。如果不刷新TTL,请考虑使用volatile-lruvolatile-lfu

# 1. 设置maxmemory(例如,10GB)
CONFIG SET maxmemory 10gb

# 2. 选择针对生存时间数据的策略
CONFIG SET maxmemory-policy volatile-ttl

实际示例:实现HTTP缓存

对于缓存完整的HTTP响应(可能并不总是设置TTL),您希望保留最常访问的数据,即使该数据已经几小时未被触及。allkeys-lruallkeys-lfu是理想选择。

# 使用LFU保留真正'热'的对象,无论其创建时间如何
CONFIG SET maxmemory-policy allkeys-lfu

监控和调优

选择策略后,持续监控至关重要。您应该通过INFO命令跟踪以下指标:

  • used_memory:您距离maxmemory限制有多近。
  • evicted_keys:Redis丢弃数据的速率。持续的高逐出率表明您的maxmemory设置对于工作负载过低,或者逐出策略过于激进。
  • 应用程序缓存命中率:最终的成功衡量标准。如果内存压力增加时命中率下降,则需要调整策略选择或maxmemory限制。

最佳实践:调优maxmemory时,始终留出安全缓冲区(例如,10-20%的空闲内存),以应对复制缓冲、命令缓冲以及Redis内部数据结构的潜在开销。

最终要点

对于通用缓存,从allkeys-lru开始;当一小部分热键主导流量时,使用allkeys-lfu;仅在必须保护不过期键时使用volatile-*策略。然后在完成策略之前,监控evicted_keys、应用程序命中率和负载下的写入错误。