关注

Redis 内存淘汰策略详解

Redis 内存淘汰策略详解

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

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

核心配置

配置项说明
maxmemory限定Redis使用的最大内存字节数
maxmemory-policy达到上限时的淘汰策略
maxmemory-samplesLRU/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

转载自CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/weixin_45787955/article/details/161401754

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--