Back to Knowledge Hub

    Redis 的内存淘汰策略是如何工作的?

    Redis
    内存管理
    淘汰策略
    性能优化

    什么是内存淘汰策略?

    Redis 内存淘汰策略是当内存使用达到上限时,自动移除部分数据以维持服务可用的机制。就像图书馆书架满了之后,需要根据规则下架部分书籍来放入新书。

    核心作用

    1. 防止内存溢出:通过 maxmemory 配置阈值(默认不限制)
    2. 维持写入能力:避免进入只读的 noeviction 状态
    3. 智能数据筛选:根据访问模式保留最有价值的数据

    8 种淘汰策略解析

    策略对照表(生产环境选型参考)

    策略名称作用范围算法特点适用场景版本要求
    noeviction不淘汰拒绝写入数据不可丢失场景2.0+
    allkeys-lru所有键近似 LRU 算法通用缓存场景(推荐)2.8+
    volatile-lru过期键近似 LRU混合持久化缓存2.8+
    allkeys-random所有键随机淘汰均匀访问模式2.0+
    volatile-random过期键随机淘汰临时数据存储2.0+
    volatile-ttl过期键剩余时间排序时效性数据2.0+
    allkeys-lfu所有键近似 LFU热点数据场景4.0+
    volatile-lfu过期键近似 LFU热点临时数据4.0+

    核心算法实现原理

    1. 近似 LRU 算法

    面试重点:理解 Redis 如何通过概率采样实现高效 LRU

    // Redis 源码片段(evict.c)
    #define EVICTION_SAMPLES_ARRAY_SIZE 16
    unsigned long estimateObjectIdleTime(robj *o) {
        return LRU_CLOCK() - o->lru;
    }
    
    void evictionPoolPopulate(dict *sampledict, struct evictionPoolEntry *pool) {
        // 随机采样 5 个键放入候选池
        for (int i = 0; i < EVICTION_SAMPLES_ARRAY_SIZE; i++) {
            // 选择具有最大空闲时间的键
            if (bestkey->lru > pool[EVPOOL_SIZE-1].idle) {
                evictionPoolPopulateItem(pool, bestkey);
            }
        }
    }
    

    算法优化点

    • 默认采样数量 5(可配置)
    • 使用固定大小候选池(16 个条目)
    • 每次淘汰选择候选池中最久未使用的键

    补充说明

    • Redis 利用全局 LRU 时钟和概率采样相结合,避免全量扫描所有键,从而降低淘汰操作的时间复杂度。
    • 在面试中,重点在于理解候选池机制及其对缓存性能的优化作用。

    2. 近似 LFU 算法

    实现机制

    • 使用 Morris 计数器概率衰减
    • 访问频率对数化存储(0-255)
    • 衰减因子配置(lfu-decay-time)
    # 查看键的 LFU 信息
    redis-cli object freq key1
    

    补充说明

    • Morris 计数器采用对数增长策略,有效防止频繁访问时计数值过快增长,同时降低内存消耗。
    • 面试常关注 LFU 算法如何更灵敏地捕捉热点数据,与传统计数器方式的区别是讨论重点。

    内存碎片整理

    触发条件及配置

    # 启用主动碎片整理
    activedefrag yes
    
    # 配置忽略小碎片区域(低于指定字节,避免不必要的整理)
    active-defrag-ignore-bytes 100mb
    
    # 当 used_memory_rss 与实际 used_memory 差异较大(碎片率超过阈值)时触发整理
    active-defrag-threshold-lower 10
    

    整理过程: Redis 内存碎片整理机制通过主动干预内存分配器中分散的数据块,实现内存紧凑化,具体步骤如下:

    1. 碎片检测:定期扫描内存,评估 used_memory_rss 与实际 used_memory 的比例,判断是否存在严重碎片问题。
    2. 候选区域选择:从内存中识别出高碎片率区域,作为数据重排的候选区域。
    3. 数据重排:将候选区域中的有效数据复制到连续的新内存空间中,以减少内存分散,并优化后续内存分配。
    4. 内存回收:逐步释放旧的、已碎片化的内存块,使得内存资源得以有效复用。
    5. 渐进整理:整个整理过程采用渐进式方式,分步执行,避免一次性大规模操作引起系统阻塞,保证前台请求的响应不会受到影响。

    生产环境配置方案

    电商秒杀场景配置示例

    # 内存限制(设置为物理内存的 3/4)
    maxmemory 12gb
    
    # 使用 LFU 策略保留热点商品数据
    maxmemory-policy allkeys-lfu
    
    # 调整 LFU 衰减周期(1 小时)
    lfu-log-factor 10
    lfu-decay-time 3600
    
    # 启用主动碎片整理
    activedefrag yes
    

    监控指标体系

    # 内存关键指标
    redis-cli info memory | grep -E "used_memory|maxmemory|mem_fragmentation_ratio"
    
    # 淘汰统计
    redis-cli info stats | grep evicted_keys
    
    # 碎片整理状态
    redis-cli info memory | grep defrag
    

    常见问题排查

    1. 内存未释放问题

    现象:达到 maxmemory 但淘汰策略未生效
    处理步骤

    # 确认策略不是 noeviction
    CONFIG GET maxmemory-policy
    
    # 检查键的过期时间(返回-1表示未设置过期时间)
    TTL mykey
    
    # 分析内存分布
    redis-cli --bigkeys
    

    2. LFU 策略热点失效

    现象:高频访问数据被意外淘汰
    处理步骤

    # 提高计数器精度(值越小精度越高)
    lfu-log-factor 10
    
    # 加快频率衰减速度(单位:分钟)
    lfu-decay-time 1800
    

    3. 内存碎片过高问题

    现象:内存使用率低但无法写入新数据
    处理步骤

    # 紧急情况手动整理
    redis-cli memory purge
    
    # 动态调整整理强度
    CONFIG SET active-defrag-cycle-min 5
    CONFIG SET active-defrag-cycle-max 10
    

    性能调优建议

    1. 容量规划:保持内存使用率 ≤70%
    2. 键值设计:避免大对象(超过 1MB)
    3. 版本升级:4.0+ 版本支持更精细策略
    4. 混合存储:冷数据持久化到磁盘

    相关推荐: