redis 4.0 前缺乏 lfu 淘汰策略与 object freq 命令,无法直接识别冷热 key;仅靠静态 ttl 无法反映真实访问热度变化,易导致冷 key 长期滞留、内存浪费。

Redis 4.0 之前无法用 OBJECT FREQ 或 MEMORY USAGE 直接识别冷热 key,但可以通过客户端埋点 + 主动 TTL 重设,把“访问频次”映射为“存活时长”,实现轻量级热度管理。
为什么不能直接依赖 Redis 自身机制
4.0 之前的 Redis 没有 LFU 淘汰策略(maxmemory-policy 不支持 allkeys-lfu 或 volatile-lfu),也没有 OBJECT FREQ 命令查访问频次。仅靠 EXPIRE 或 SET ... EX 是静态的,一旦设好就固定不变,无法反映真实访问热度变化。
常见错误是:所有 key 统一设 30 分钟过期,结果大量低频 key 长期占内存,而真正高频的 key 却没被优先保留。
- 冷 key 会长期滞留,直到自然过期,期间持续占用内存和连接资源
- 没有访问反馈机制,无法区分“刚写入但还没被读”的新 key 和“写入后从未被读”的死 key
- 运维只能靠
INFO memory看总量,无法定位具体哪些 key 属于“非热点但未释放”
客户端埋点 + 动态重设 TTL 的核心逻辑
本质是把“key 是否被访问”这个事件,在每次 GET、HGET、SMEMBERS 等读操作后,由应用层主动触发一次 EXPIRE,让活跃 key 的 TTL 被不断刷新,冷 key 则因无人访问而自然淘汰。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
关键不是“统计次数”,而是“保活信号”——只要被读过,就续命;没被读,就到期。
- 只在读操作后调用
EXPIRE,写操作(如SET)不重设,避免干扰初始缓存策略 - TTL 值建议设为动态区间,比如
60 + random(0, 30)秒,防批量 key 同时过期 - 对已过期的 key 不做重设(先
EXISTS判断),避免无效命令压 Redis 连接 - 若使用连接池(如 JedisPool / Lettuce),确保
EXPIRE和前一个读命令在同一个连接上执行(多数客户端默认保证)
Java 示例:Lettuce 客户端封装读+续期
// 伪代码,实际需结合你自己的 CacheClient 封装
public <t> T getAndRefresh(String key, Class<t> type) {
String json = redisClient.get(key); // 执行 GET
if (json != null && !json.isEmpty()) {
// 只对存在的 key 续期,且加随机抖动
int baseTtl = 60;
int jitter = ThreadLocalRandom.current().nextInt(0, 31);
redisClient.expire(key, baseTtl + jitter); // 执行 EXPIRE
return objectMapper.readValue(json, type);
}
return null;
}</t></t>
注意:redisClient.get() 和 redisClient.expire() 必须用同一个同步连接实例。若用异步 API(如 Lettuce 的 RedisStringReactiveCommands),需用 pipeline 或事务包裹,否则可能跨连接导致 EXPIRE 失效。
容易被忽略的三个边界问题
这套方案看似简单,但线上踩坑多集中在以下三点:
- 高并发下同一 key 多次
GET触发多次EXPIRE,虽无害但浪费带宽——可加本地线程级去重(如ThreadLocal<set>></set>记录本周期已续期的 key) - 某些 key 是“写多读少”型(如用户 session 写入频繁但读取稀疏),这类 key 会被误判为冷 key——需按业务类型白名单跳过续期(如以
session:开头的 key 不走此逻辑) - Redis 持久化 RDB/AOF 文件里会记录每次
EXPIRE命令,若续期太密,可能增大 AOF rewrite 频率——建议单 key 续期间隔不低于 10 秒,或改用PEXPIREAT设置绝对毫秒时间戳,减少命令体积
真正的难点不在埋点本身,而在于如何定义“冷”的时间尺度:设太短(如 30 秒),正常低频访问的 key 也会被误清;设太长(如 24 小时),起不到释放内存的效果。这个阈值必须结合你业务的 P95 访问间隔来定,不能拍脑袋。










