当前位置:首页 > 文章列表 > 数据库 > Redis > Redis LFU 淘汰中的计数衰减参数怎样理解

Redis LFU 淘汰中的计数衰减参数怎样理解

来源:17golang原创 2026-10-09 08:53:51 0浏览 收藏

lfu-decay-time 表示 Redis LFU 频率计数减少 1 个单位所对应的时间窗口,单位是分钟。默认值为 1,意味着每经过 1 分钟,计数在被重新计算时最多按经过的完整周期递减;设为 0 则不做衰减。它不是键的 TTL,也不会每隔一段时间把所有键的计数统一清零。

官方淘汰策略文档:https://redis.io/docs/latest/develop/reference/eviction/

要点速览
  • 数值越小,旧热点降温越快;数值越大,历史热度保留越久。
  • 衰减是按已过去的完整周期扣减计数,不是乘一个百分比。
  • lfu-log-factor 控制计数增长概率,lfu-decay-time 控制热度消退速度。

这个参数控制的到底是什么

Redis 的 LFU 不是为每个键保存一个无限增长的精确访问次数,而是在键的元数据中保存一个 8 位对数频率计数器。计数器上限为 255,访问时采用概率方式增长;为了避免几小时前或几天前的热点永久占据优势,Redis 又引入时间衰减。

可以把衰减理解成下面的关系:经过的完整衰减周期数约等于“距离上次记录的分钟数 ÷ lfu-decay-time”,当前计数再减去这些周期数,最低降到 0。例如参数为 5 时,完整经过 20 分钟对应 4 个衰减周期,而不是在第 5 分钟直接归零。

配置值含义典型影响
0计数不随时间衰减历史热点可能长期占优,除非访问模式非常稳定,否则要谨慎
1每 1 分钟形成一个衰减周期默认值,热点能较快随访问变化调整
5每 5 分钟形成一个衰减周期短暂停顿不易让长期热点快速失去优势
60每 60 分钟形成一个衰减周期历史热度记忆很长,突发热点退出也更慢

LFU 元数据怎样保存时间和频率

在 LFU 策略下,Redis 使用 24 位元数据同时表达时间与频率:高 16 位保存分钟级的最近衰减时间,低 8 位保存对数频率计数。lfu-decay-time 参与“经过多少衰减周期”的计算,OBJECT FREQ 则让管理员读取键当前的对数频率计数。

Redis LFU 键元数据、衰减周期和 OBJECT FREQ 之间的静态关系图
图1:Redis LFU 元数据结构说明图;展示时间字段、频率字段与衰减参数的关系,不是运行截图。

一个容易误解的细节是:Redis 不会由后台任务每分钟遍历所有键并修改计数。衰减是惰性计算的,键在被访问、更新、作为淘汰候选检查,或者通过相关命令读取频率时,才根据时间差计算应扣减多少。这种设计避免了为整个键空间持续扫描,但也意味着“配置改完以后,所有键的数值马上同时变化”并不是正确预期。

用 OBJECT FREQ 观察衰减效果

OBJECT FREQ key 返回的是对数频率计数,不是精确请求总数,而且只有在 maxmemory-policy 选择 LFU 策略时才可使用。测试时先确认策略和参数,再建立访问量不同的键进行观察。

# 查看当前淘汰策略、增长因子和衰减时间,避免在错误策略下解释频率值
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 SET demo:hot value
redis-cli SET demo:cold value

# 给热键增加访问,概率计数不会与循环次数一一对应
for i in {1..200}; do redis-cli GET demo:hot >/dev/null; done

# 读取当前对数频率计数,用于同一环境中的相对比较
redis-cli OBJECT FREQ demo:hot
redis-cli OBJECT FREQ demo:cold

等待若干完整衰减周期后再次读取,可以看到计数逐步降低。不要拿 OBJECT FREQ 当 QPS 指标,也不要期待 200 次 GET 就一定增加 200;计数增长本来就是概率性的。验证重点是相同配置下热键与冷键的相对差异,以及改变衰减时间后旧热点退出的速度是否符合业务周期。

要临时调整测试实例,可以这样做:

# 把衰减周期改为 5 分钟,观察旧热点是否保留得更久
redis-cli CONFIG SET lfu-decay-time 5

# 读取生效值;如需重启后仍保留,还要按部署方式更新配置来源
redis-cli CONFIG GET lfu-decay-time

# 查看淘汰累计数,结合命中率与业务延迟判断变化,不只看单个键
redis-cli INFO stats | grep -E 'evicted_keys|keyspace_hits|keyspace_misses'

别把三个 LFU 相关参数混在一起

LFU 的实际淘汰结果不是只由一个参数决定。增长、衰减和候选采样属于三个不同边界:lfu-log-factor 决定高频键继续增长有多难,lfu-decay-time 决定历史热度消退有多快,maxmemory-samples 决定每次淘汰近似算法观察多少候选键。

Redis LFU 增长参数、衰减参数与候选采样参数的静态边界关系图
图2:Redis LFU 调节参数边界说明图;三个参数共同影响淘汰判断,但职责不同。
参数主要职责调大后的方向常见误区
lfu-log-factor控制访问计数的概率增长高频计数增长更慢,需要更多命中才能上升把它当成衰减速度
lfu-decay-time控制计数每减少 1 的时间窗口旧热度保留更久把它当成 TTL 或清零周期
maxmemory-samples控制近似淘汰每次比较的候选数量更接近理想选择,但消耗更多 CPU认为它会改变单个键的频率计数

此外,allkeys-lfu 可以从全部键中按 LFU 近似淘汰,而 volatile-lfu 只在设置了过期时间的键中选择候选。如果使用后者但大量键没有 TTL,没有资格进入候选集合的键就不会因为频率低而被淘汰。排查效果时要先确认策略边界,再看计数参数。

不同访问模式怎样选择衰减时间

默认值通常应作为起点,只有当业务的热点周期和默认衰减明显不匹配时再调整。可以先按访问模式判断方向:

  • 热点以分钟为单位快速切换:保持较小值,让旧热点尽快降温,避免活动页、榜单或突发事件结束后仍占据缓存。
  • 热点跨小时稳定:可以评估适度增大,减少短时抖动对长期热点的影响。
  • 访问非常稀疏:过大的值会让偶然被访问过的键长时间保留优势,应结合内存压力和 miss 成本判断。
  • 冷热差距极大:先观察 OBJECT FREQ 的分布,再决定是改衰减时间还是增长因子;只动一个参数更容易解释结果。

不要根据“多久没有访问就淘汰”来反推该参数,因为 LFU 不是精确的空闲时间淘汰器。计数衰减后,Redis 仍要在内存达到 maxmemory、写入需要释放空间时,从采样候选中选择更不常用的键。没有内存压力时,低频键不会仅因计数下降而自动删除。

上线调整时要观察哪些风险

调整应先在与生产流量形态相近的测试实例或小流量实例进行,并保留变更前的策略、参数和监控基线。至少同时观察命中率、淘汰数、内存使用、写入延迟和关键业务回源压力,不能只抽查几个键的 OBJECT FREQ。

  1. 记录现有 maxmemory-policy、lfu-log-factor、lfu-decay-time 和 maxmemory-samples。
  2. 一次只调整一个变量,并让观察窗口覆盖多个真实热点周期。
  3. 比较 keyspace_hits、keyspace_misses、evicted_keys 与上游回源延迟。
  4. 确认配置的持久化方式;仅执行 CONFIG SET 可能不会自动修改容器、配置文件或配置中心。
  5. 准备回退值,若 miss 增长或旧热点保护过强,就恢复原参数而不是继续叠加调整。

常见问题

lfu-decay-time=1 是每分钟清零吗?

不是。它表示每经过一个完整分钟周期,当前计数可减少 1,直到最低为 0;不会每分钟把所有键统一清零。

设为 0 会让键永远不被淘汰吗?

不会。0 只表示频率计数不因时间衰减。键仍可能因为相对频率较低、候选采样结果以及内存压力而被淘汰,但历史热点更容易长期保留较高计数。

改完参数后为什么 OBJECT FREQ 没有立刻整体下降?

因为衰减是惰性计算,不是后台统一扫描。键被访问、更新、读取频率或进入淘汰候选检查时,才会根据经过时间计算新的计数。

可以只看 OBJECT FREQ 决定参数吗?

不够。它适合解释单个键的相对热度,还要同时看命中率、淘汰数、内存压力、延迟和上游回源成本,才能判断参数是否真正改善了缓存效果。

LFU 和 TTL 会互相替代吗?

不会。TTL 决定键何时过期,LFU 决定内存压力下哪些候选更应该被淘汰。二者可以同时使用,但语义和触发条件不同。

参考资料

  • Redis Key eviction:https://redis.io/docs/latest/develop/reference/eviction/
  • Redis 官方配置示例:https://github.com/redis/redis/blob/unstable/redis.conf
  • OBJECT FREQ:https://redis.io/docs/latest/commands/object-freq/
  • Redis 淘汰实现源码:https://github.com/redis/redis/blob/unstable/src/evict.c
版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
B.Loop 中修改循环外变量为什么会影响基准结果B.Loop 中修改循环外变量为什么会影响基准结果
上一篇
B.Loop 中修改循环外变量为什么会影响基准结果
用 B.Loop 正确排除一次性初始化开销
下一篇
用 B.Loop 正确排除一次性初始化开销
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    386次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    468次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    475次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    415次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    241次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码