[Redis小技巧11]Redis Key 过期策略与内存淘汰机制:深度解析与实战指南

在高并发、低延迟的现代应用架构中,Redis 作为高性能内存数据库,广泛用于缓存、会话存储、排行榜等场景。

然而,随着数据量增长,如何高效管理内存、合理释放过期数据,成为保障系统稳定性的关键。

一、Key 过期策略:惰性删除 vs 定期删除

Redis 并非在 Key 到期瞬间立即删除,而是采用 "惰性删除 + 定期删除" 的混合策略,兼顾性能与内存回收效率。

1. 惰性删除(Lazy Expiration)

  • 触发时机:当客户端尝试访问某个 Key 时,Redis 会检查其是否已过期。
  • 行为:若已过期,则同步删除该 Key 并返回空值。
  • 优点:CPU 友好,仅在必要时执行删除。
  • 缺点:过期但未被访问的 Key 会长期占用内存。
c 复制代码
// 伪代码示意
if (key_exists && key_has_ttl && current_time > expire_time) {
    delete_key(key);
    return NULL;
}

2. 定期删除(Active Expiration)

  • 触发机制:Redis 后台每秒运行 10 次(即每 100ms 一次)过期扫描。
  • 扫描逻辑
    • 随机采样 ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP(默认 20)个设置了过期时间的 Key;
    • 删除其中已过期的 Key;
    • 若过期 Key 比例 > 25%,则重复采样(最多 25ms,避免阻塞主线程)。
  • 目标:主动回收"僵尸"过期 Key,防止内存泄漏。

3. Key 过期检查流程

二、内存淘汰策略(Eviction Policies)

当 Redis 内存使用达到 maxmemory 限制时,将根据配置的淘汰策略决定如何释放空间。

1. 配置方式

bash 复制代码
# redis.conf
maxmemory 4gb
maxmemory-policy allkeys-lru

或运行时动态设置:

bash 复制代码
CONFIG SET maxmemory 4gb
CONFIG SET maxmemory-policy volatile-lfu

2. 八种淘汰策略详解

策略名称 作用范围 是否依赖 TTL 淘汰依据 典型场景
noeviction 所有 Key 不淘汰,写操作报错 重要数据禁止丢失
allkeys-lru 所有 Key 最近最少使用 通用缓存
allkeys-lfu 所有 Key 最不经常使用 热点数据缓存
allkeys-random 所有 Key 随机淘汰 数据价值相近
volatile-lru 仅带 TTL 的 Key 最近最少使用 缓存 + 会话
volatile-lfu 仅带 TTL 的 Key 最不经常使用 带过期的热点缓存
volatile-random 仅带 TTL 的 Key 随机淘汰 临时数据
volatile-ttl 仅带 TTL 的 Key 剩余存活时间最短 快速清理即将过期数据

LRU 与 LFU 实现说明

Redis 并未使用传统链表实现 LRU/LFU,而是采用 近似算法 (Approximated LRU/LFU)以节省内存。通过在 Key 的 redisObject 中维护一个 24 位的 LRU 时钟或 LFU 计数器,结合采样(默认 5 个候选 Key)进行淘汰决策。

3.内存淘汰决策流程

三、核心命令与使用建议

命令 用途 注意事项
EXPIRE key seconds 设置 Key 过期时间 覆盖已有 TTL
PEXPIRE key ms 毫秒级过期 更精确
TTL key 查看过期剩余秒数 返回 -2(不存在)、-1(无过期)
PERSIST key 移除过期时间 转为永久 Key
MEMORY USAGE key 查看 Key 内存占用 辅助容量规划
INFO memory 查看内存统计 关注 used_memory, maxmemory
CONFIG GET maxmemory* 获取内存配置 诊断淘汰行为

最佳实践

  • 避免对大量 Key 单独设置不同 TTL,会增加过期字典负担;
  • 对于缓存场景,优先使用 allkeys-lruallkeys-lfu,而非 volatile-*,除非你明确只希望淘汰带 TTL 的数据;
  • 监控 evicted_keys 指标(通过 INFO stats),若持续增长,说明内存不足或策略不合理。

四、典型应用场景

场景 1:用户会话缓存

  • 需求:登录态 30 分钟过期,自动清理。
  • 方案SET session:123 user_data EX 1800
  • 淘汰策略volatile-lru(仅清理会话类 Key)

场景 2:商品详情缓存(高并发读)

  • 需求:缓存热点商品,内存有限。
  • 方案 :预加载 + allkeys-lfu,保留高频访问商品。
  • 优势:LFU 比 LRU 更适合识别"长期热点"。

场景 3:防缓存击穿

  • 问题:大量请求同时穿透失效缓存,压垮 DB。
  • 对策:使用逻辑过期(如 JSON 中嵌入 expire_time)+ 后台异步刷新,避免依赖 Redis TTL 触发删除。

五、高频面试题

Q1:Redis 为什么不用定时器为每个 Key 单独设置删除任务?

:定时器(如时间轮)虽精准,但海量 Key 下内存和调度开销巨大。Redis 选择惰性+定期采样的折中方案,在 CPU 与内存之间取得平衡。

Q2:LRU 和 LFU 在 Redis 中是如何近似实现的?

:Redis 使用 24 位字段存储 LRU 时钟(秒级精度)或 LFU 计数器(高 16 位为时间戳,低 8 位为访问频次)。淘汰时随机采样 5 个 Key,比较其 LRU/LFU 值,淘汰最旧/最少使用的。

Q3:volatile-ttlallkeys-lru 有何区别?何时用前者?

volatile-ttl 仅作用于带 TTL 的 Key,按剩余时间排序;适用于"快过期的数据优先删"的场景,如临时验证码。而 allkeys-lru 适用于通用缓存,不依赖 TTL。

Q4:如何监控 Redis 是否因淘汰策略导致数据异常丢失?

:通过 INFO stats 查看 evicted_keyskeyspace_hits/misses。若 evicted_keys 激增且命中率下降,需扩容或调整策略。

Q5:maxmemory 设置为 0 表示什么?

:表示无内存限制(64 位系统)。但在生产环境强烈建议显式设置,防止 OOM 导致进程被 kill。

相关推荐
AOwhisky15 分钟前
Redis 学习笔记(第一期):概述、安装配置与核心理论
运维·数据库·redis·笔记·学习·云计算
ytttr87323 分钟前
C# 定时数据库备份工具
开发语言·数据库·c#
睡不醒男孩03082334 分钟前
自建 Prometheus+Grafana 与 CLUP 深度监控 PG 集群有什么区别?
数据库·oracle
AOwhisky43 分钟前
Redis 学习笔记(第四期):高可用与集群(哨兵 + Cluster + 容器化)
linux·运维·数据库·redis·笔记·学习·缓存
猫猫聚会Ing1 小时前
数据库设计 Prompt 提示词 - 构建与迭代
数据库
上海云盾-小余1 小时前
源站隐藏实战:规避裸 IP 被直接攻击的完整方案
数据库·网络协议·tcp/ip
微学AI2 小时前
时序大模型 TimechoAI 赋能工业时序数据底层技术优势与实操
数据库·大模型·时序大模型
北顾笙9802 小时前
MYSQL-day03
数据库·sql·mysql
MXsoft6182 小时前
**混合云统一监控实践:私有云+公有云的一体化运维方案**
运维·网络·数据库
瀚高PG实验室3 小时前
java中间件无法连接数据库
java·数据库·中间件·瀚高数据库