登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  数据库 >  Redis

Redis eviction-policy 怎样选择 LRU 或 LFU

来源:17golang原创

时间:2026-10-20 23:26:14 135浏览 收藏

所有键都能从权威数据源重建、暂时没有明确访问模型时,可从 allkeys-lru 建立基线;若有一批持续反复访问的热点、同时夹杂大量偶发访问,则值得对照试用 allkeys-lfu。这不是“LFU 比 LRU 高级”的排序,而是用最近访问还是近似访问频率,预测下一次会用到什么。

Redis 官方地址:https://redis.io/

本文的命令用于有管理权限、可丢弃数据的隔离测试实例,不直接套用线上;示例没有在本文环境执行,也没有预设任何命中率提升结果。实际参数名为 maxmemory-policy,不是名为 eviction-policy 的配置项。

命中下降时先确认是不是淘汰造成的

先问缓存未命中是否真的由容量淘汰造成。近期新增一批冷数据、TTL 变短、业务请求换了一类,都可能让命中率下降,改 LRU 或 LFU 未必解决。

# 在已配置连接信息的测试实例读取实际配置,不假设当前策略
redis-cli CONFIG GET maxmemory-policy
redis-cli CONFIG GET maxmemory
redis-cli CONFIG GET maxmemory-samples
# 保留同一实例的观测起点,稍后取同样的信息计算增量
redis-cli INFO stats
redis-cli INFO memory

evicted_keys 是因 maxmemory 限制而淘汰的键数,expired_keys 是过期事件数。比较同一窗口内的变化:淘汰没有明显发生却有大量过期,优先调查 TTL 和请求分布;只有确认容量竞争参与了问题,策略对比才有针对性。字段含义见 INFO 官方说明。

先定候选范围再比较 LRU 和 LFU

策略分成“候选范围”与“选择依据”两层:allkeys 覆盖全部键;volatile 只让带 TTL 的键参加淘汰。LRU 使用最近访问信息,LFU 使用有衰减的近似频率;两者都采用采样近似,不是对全库做精确排名。volatile 没有可用候选时不能凭空释放永久键。

负载假设先比较什么需要注意
所有数据都可重建,访问模式尚不明确allkeys-lru 基线先建立业务指标,不把默认选择当最终结论
近期活跃集合不断换新LRU 与 LFU 的适应性关注热点换代时的回源压力
稳定热点夹杂偶发批量读取LFU 是否更能保留反复访问的数据这只是测试假设,频率不等于业务价值
同实例混放不可随意丢失的数据先解决实例隔离与可淘汰范围不要为了命中率切成 allkeys

这里关于负载的选择是工程判断,不是算法保证。TTL 决定有效期,不等于“到期前不会淘汰”;volatile 中的键也可能提前被容量淘汰。候选范围与近似算法依据 Redis 淘汰文档。

候选范围与选择依据两个边界中的六个节点
图1:静态结构说明图。上组解释哪些键可参与,下组区分最近访问与近似频率;连线表示归属,不表示执行顺序,也不是运行截图。

固定容量与访问样本后再切换

用相同缓存容量、相同对象大小分布和相同请求序列,分别观察两种策略。序列至少包括平稳热点、热点换代和一次性读取这几类业务确实会出现的负载;这是对照方案,不是要往生产实例灌数据。

下面仅演示已确认原策略是 allkeys-lru、所有键均可重建时的单变量切换。保留 maxmemory、TTL、采样数和客户端逻辑,不同时改变一串参数。

# 先抄录当前配置;若不是预期的测试实例或原策略,停止本示例
redis-cli CONFIG GET maxmemory-policy
redis-cli CONFIG GET lfu-log-factor
redis-cli CONFIG GET lfu-decay-time
# 仅在上述前提成立时试用 LFU,不在此处降低内存上限
redis-cli CONFIG SET maxmemory-policy allkeys-lfu
# 读取当前值只确认配置已切换,不代表命中率已经改善
redis-cli CONFIG GET maxmemory-policy

LFU 的计数是概率近似值,不是精确 GET 次数。lfu-log-factor 控制增长尺度,lfu-decay-time 影响旧热度淡出的尺度。本轮选型先记录二者,不顺手调优,避免无法区分策略和参数的贡献。配置解释参见 Redis 8.6 配置注释。

CONFIG SET 改的是运行时配置,使用方式见 命令文档。若环境不允许该命令,应走该环境支持的配置管理入口,不尝试绕过管理限制。

回退策略不等于恢复缓存现场

# 仅对应原值确认为 allkeys-lru 的测试实例;其他原值必须原样恢复
redis-cli CONFIG SET maxmemory-policy allkeys-lru
# 确认恢复的是策略配置,而不是已经淘汰的数据
redis-cli CONFIG GET maxmemory-policy

恢复原配置不能找回刚刚淘汰的键,也不能把访问统计恢复到切换前。Redis 8.6 的对象命令实现明确提醒:LRU 与 LFU 在运行时互换后,相关信息需要时间调整。因此不承诺固定几秒就稳定,也不要频繁来回切换,拿瞬间波动比较优劣。参见 对象信息实现中的切换说明。

测试配置不应自动固化到重启配置。确定长期采用后,再按配置管理流程同步;自管且以配置文件启动的实例可了解 CONFIG REWRITE,它将当前有效配置写回文件,不只是写回这一项。未使用配置文件启动时该命令会报错,不能把它放进通用试验脚本。见 CONFIG REWRITE 文档。

用业务代价决定保留哪种策略

分别记录两种策略的稳定观察窗口。窗口命中率按 Δkeyspace_hits / (Δkeyspace_hits + Δkeyspace_misses) 计算;分母为零就没有可比较样本,计数重置或实例重启则重新开始该窗口。Redis 的实例级命中不能直接代表某个商品接口或某个租户的命中,应同时使用应用侧指标。

把观测拆成三组:缓存观测记录命中增量、淘汰增量;回源观测记录回源请求与回源延迟;决策约束记录错误预算和容量预算。即使命中稍有变化,也要问数据库是否承受更多查询、重要接口是否超时。不同键的重建代价不同,LRU 和 LFU 都不会自动理解业务价值。这些是建议采用的业务判断条件,并非本文测得的表现。

缓存观测回源观测和决策约束三组指标的静态关系
图2:静态结构说明图。缓存命中与淘汰、回源请求与延迟、预算约束共同构成决策材料;没有虚构性能数值,也不代表实际监控页面。

上线前约定回退条件,例如回源延迟或错误率超出团队已有预算就停止扩大试用。没有真实基线时先补监控,不在这里编造通用告警阈值。若访问序列、对象体积或流量比例不一致,记录差异,不把结果归因于一个策略名。

把选型结论写成带条件的记录

决策记录至少保留:哪些键允许淘汰、原策略与候选策略、缓存容量、请求类型、观察窗口、回源代价、回退条件。结论应类似“这类稳定热点的可重建缓存,在相同容量和请求样本下优先继续评估 LFU”,而不是“所有 Redis 都切 LFU”。

带 TTL 的缓存一定要用 volatile 吗?

不一定。TTL 是有效期需求;是否用 volatile 取决于是否要限制淘汰候选。纯缓存也可以用 allkeys,让所有缓存键参与容量竞争。

切 LFU 后命中率没升,是配置没生效吗?

不必然。先确认实际策略,再排除观察期、访问模式和容量条件差异;负载本来不适合 LFU 也可能没有收益。

为了保护业务数据可以只改回 LRU 吗?

不可以这样理解。allkeys-lru 与 allkeys-lfu 都允许淘汰所有键;不可随意丢失的数据首先需要明确的数据保护与部署边界。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>