Redis 内存淘汰策略详解

Redis 内存淘汰策略详解

一、为什么需要淘汰策略?

Redis是一个基于内存的数据库,所有数据都存储在内存中。然而内存是稀缺资源,当内存使用达到上限时,必须要有一种机制来决定哪些数据该被清理。

核心配置

配置项 说明
maxmemory 限定Redis使用的最大内存字节数
maxmemory-policy 达到上限时的淘汰策略
maxmemory-samples LRU/LFU算法采样的数量

Redis对象结构

Redis每个键值对都是一个redisObject,包含以下字段:

字段 说明
type 数据类型(String/List/Hash等)
encoding 编码方式(int/embstr/raw等)
lru 记录对象空转时长(LRU时钟)
refcount 引用计数,对象被复用的次数
ptr 指向实际数据的指针

二、八种淘汰策略

分类总览

复制代码
                    +-------------------------+
                    |    淘汰策略选择         |
                    +-------------------------+
                              |
        +---------------------+---------------------+
        |                     |                     |
        v                     v                     v
+---------------+    +-----------------+    +---------------+
|  volatile-*  |    |    allkeys-*    |    | no-eviction   |
| (过期key中)  |    |   (所有key中)   |    | (禁止淘汰)    |
+---------------+    +-----------------+    +---------------+

1. volatile-lru(LRU - 最近最少使用)

算法思想:

从已设置过期时间的键中,选择最近最长时间未被使用的key进行淘汰。

适用场景:

  • 数据有明显的冷热之分
  • 希望保留热点数据,过期数据自然淘汰

工作原理:

  • RedisObject中的lru字段记录最近一次访问的时间戳
  • 淘汰时遍历所有带过期时间的key
  • 选择lru值最小(最久未被访问)的key淘汰

配置示例:

复制代码
maxmemory-policy volatile-lru
maxmemory-samples 5

2. volatile-lfu(LFU - 最少次数使用)

算法思想:

从已设置过期时间的键中,选择最近一段时间内访问次数最少的key进行淘汰。

适用场景:

  • 数据访问频率有明显规律
  • 需要淘汰低频数据保留高频数据

工作原理:

  • RedisObject中的lru字段高16位存储分钟级别的访问时间,低8位存储访问计数器
  • 淘汰时选择refcount最小(访问次数最少)的key淘汰

3. volatile-ttl(TTL - 最近要过期)

算法思想:

从已设置过期时间的键中,优先淘汰剩余存活时间最短的key。

适用场景:

  • 数据有明确的有效期
  • 希望优先清理即将过期的数据

工作原理:

  • 每个key都记录了过期时间戳
  • 淘汰时计算各key的剩余TTL
  • 优先淘汰TTL最小(最快过期)的key

4. volatile-random(随机淘汰)

算法思想:

从已设置过期时间的键中,随机选择某个key进行淘汰。

适用场景:

  • 数据重要性相近
  • 需要快速释放内存而不关心具体淘汰哪个

5. allkeys-lru(全库LRU)

算法思想:

从所有键中选择最近最长时间未被使用的key进行淘汰。

适用场景:

  • 全部数据都有被访问的可能
  • 缓存空间明显不足,需要释放内存
  • 没有明确过期时间的数据也需要清理

特点:

与volatile-lru相比,选择范围是所有key,不限于带过期时间的key。


6. allkeys-lfu(全库LFU)

算法思想:

从所有键中选择访问次数最少的key进行淘汰。

适用场景:

  • 所有数据都需要管理
  • 希望保留高频访问数据

7. allkeys-random(全库随机)

算法思想:

从所有键中随机选择某个key进行淘汰。

适用场景:

  • 数据访问频率相近
  • 需要快速腾出内存空间

8. no-eviction(禁止淘汰)

行为:

当内存使用达到maxmemory时,不淘汰任何数据,写入操作直接失败。

返回值:

复制代码
(error) OOM command not allowed when used memory > maxmemory

适用场景:

  • 作为纯粹的功能服务,不希望丢失任何数据
  • 对内存有严格监控,到达阈值后人工干预

三、策略对比

策略 选择范围 选择依据 特点
volatile-lru 过期key 最近最少使用 保留热点,淘汰冷数据
volatile-lfu 过期key 最近最少使用次数 保留高频,淘汰低频
volatile-ttl 过期key 最短剩余TTL 优先淘汰快过期的
volatile-random 过期key 随机 快速释放,不挑数据
allkeys-lru 所有key 最近最少使用 激进淘汰,适合缓存场景
allkeys-lfu 所有key 最近最少使用次数 保留高频访问数据
allkeys-random 所有key 随机 快速腾空间
no-eviction 只读不写,禁止淘汰

四、配置建议

选择策略的决策树

复制代码
需要淘汰数据?
    |
    +--否--> no-eviction
    |
    +--是--> 数据有明确过期时间?
                |
                +--否--> 全部数据都是候选
                |           |
                |           +---> 区分访问频率?
                |                       |
                |                       +--是--> allkeys-lfu
                |                       |
                |                       +--否--> allkeys-lru 或 allkeys-random
                |
                +--是--> 区分访问频率?
                            |
                            +--是--> volatile-lfu
                            |
                            +--否--> volatile-lru

推荐配置

通用缓存场景:

复制代码
maxmemory 2gb
maxmemory-policy allkeys-lru
maxmemory-samples 5

内存敏感场景:

复制代码
maxmemory 1gb
maxmemory-policy volatile-lru
maxmemory-samples 5

五、LRU算法采样

Redis默认使用采样方式近似实现LRU,而不是精确计算所有key。

复制代码
maxmemory-samples 5  # 采样5个key进行对比

采样数量影响:

采样数 近似精度 内存开销
5 约60%准确
10 约80%准确
16 约90%准确

采样数越大越接近精确LRU,但CPU开销也相应增加。


六、面试追问

问题 回答要点
Redis LRU和MySQL LRU有什么区别? MySQL是精确LRU,需要维护有序链表;Redis是采样近似LRU,性能更高
LFU比LRU好在什么地方? LFU能识别高频热点数据,LRU可能误杀周期性访问的数据
为什么需要随机策略? 当数据访问频率相近时,随机策略能快速释放内存
no-eviction有什么用? 保护数据不丢失,达到阈值后人工介入排查

根据零声教育教学写作https://github.com/0voice

相关推荐
洛水水17 小时前
redis缓存:雪崩、穿透、击穿详解
数据库·redis·缓存
暴躁小师兄数据学院17 小时前
【AI大数据工程师特训笔记】第01讲:数据库基本概念
大数据·数据库·笔记
杨云龙UP17 小时前
Oracle Flashback Query 实战练习:误更新、误删除数据如何快速找回?
linux·运维·数据库·sql·oracle·flashback
basketball61617 小时前
SQL 条件聚合 使用方法总结
服务器·数据库·sql
一只fish17 小时前
Oracle官方文档翻译《Database Concepts 26ai》第12章-数据并发与一致性
数据库·oracle
Crazy_eater17 小时前
Mysql(1)
数据库·mysql
Mr. zhihao18 小时前
Redis 集群分区思想的演进:从哈希取余到虚拟槽
redis·哈希算法
万岳科技系统开发18 小时前
外卖系统小程序开发方案解析:直播、团购与外卖功能如何融合
数据库·小程序·架构