Valkey Community

过期与淘汰:TTL 与 maxmemory

5 分钟读懂 Key 过期机制、主动 vs 惰性过期,以及 maxmemory 与 8 种淘汰策略的选择。

Valkey 的内存控制有两层:TTL(单 Key 过期)和 maxmemory + 淘汰策略(达到上限时整体回收)。 两者配合,才能让缓存既新鲜又稳定不挂。

TTL:单 Key 过期

命令作用
EXPIRE key seconds设置秒级 TTL
PEXPIRE key milliseconds毫秒级 TTL
EXPIREAT key unix-seconds指定到期时间戳
PEXPIREAT key unix-ms毫秒时间戳
TTL / PTTL key查剩余秒 / 毫秒
EXPIRETIME / PEXPIRETIME key查绝对到期时间戳
PERSIST key移除 TTL,变成永久
127.0.0.1:6379> SET token:abc xxx
OK
127.0.0.1:6379> EXPIRE token:abc 600
(integer) 1
127.0.0.1:6379> TTL token:abc
(integer) 600
127.0.0.1:6379> PERSIST token:abc
(integer) 1
127.0.0.1:6379> TTL token:abc
(integer) -1

TTL 返回 -1 表示永久,-2 表示 Key 不存在。

SET 一次搞定 TTL

127.0.0.1:6379> SET page:home "<html>..." EX 60
127.0.0.1:6379> SET page:home "<html>..." PX 60000
127.0.0.1:6379> SET page:home "<html>..." EXAT 1718260800
127.0.0.1:6379> SET page:home "<html>..." EX 60 KEEPTTL

KEEPTTL 是覆盖写入但保留原 TTL,很适合「刷新内容但不重置剩余过期时间」的场景。

Hash 字段级 TTL 见 Hash

主动 vs 惰性过期

Valkey 用两种方式回收过期 Key:

  • 惰性(lazy):访问到一个过期 Key 时,立即删除并按未命中返回。
  • 主动(active):后台周期性地随机抽样 20 个带 TTL 的 Key,删除其中已过期的; 如果过期比例超 25% 就立刻再抽一轮,否则等到下次循环。

这种「抽样 + 比例」策略避免一次扫描全库阻塞主线程。 副作用是冷数据可能在过期后还活着一段时间,只占内存不返回——这正是 maxmemory 兜底的位置。

maxmemory:内存上限

127.0.0.1:6379> CONFIG SET maxmemory 1gb
OK
127.0.0.1:6379> CONFIG GET maxmemory-policy
1) "maxmemory-policy"
2) "noeviction"

写入即将超限时,Valkey 根据 maxmemory-policy 决定怎么办。

8 种淘汰策略

策略范围选择依据
noeviction(默认)不淘汰,写命令直接报错 OOM
allkeys-lru所有 Key最近最少使用
allkeys-lfu所有 Key最不常使用(按访问频率)
allkeys-random所有 Key随机淘汰
volatile-lru仅带 TTL 的 Key最近最少使用
volatile-lfu仅带 TTL 的 Key最不常使用
volatile-random仅带 TTL 的 Key随机淘汰
volatile-ttl仅带 TTL 的 Key优先淘汰剩余 TTL 短的

默认 noeviction 意味着内存满了写入会失败。生产做纯缓存的实例几乎都应改成 allkeys-lruallkeys-lfu

volatile-* 系列只在带 TTL 的 Key 中挑;如果没 Key 带 TTL,行为就退化成 noeviction,写入照样报错。

抽样精度:maxmemory-samples

Valkey 的 LRU / LFU 不是严格遍历全表,而是抽样近似。默认每轮抽 5 个 Key 选最差的踢。

127.0.0.1:6379> CONFIG GET maxmemory-samples
1) "maxmemory-samples"
2) "5"
127.0.0.1:6379> CONFIG SET maxmemory-samples 10
OK

10 已经非常接近真实 LRU 但 CPU 多一点,对大多数业务 5 就够。LFU 推荐 10

选哪种策略?决策树

  • 纯缓存,访问越频繁越要留 → allkeys-lfu
  • 纯缓存,按「最近用过」即可 → allkeys-lru
  • 混合用:有持久数据 + 有 TTL 缓存,不希望持久数据被踢 → volatile-lruvolatile-lfu
  • 不想 Valkey 自动删任何东西,宁可写失败 → noeviction(默认)

监控 OOM 与淘汰

指标(INFO memory / INFO stats含义
used_memory_human当前占用
maxmemory_human上限
evicted_keys已被淘汰的总数
expired_keys因 TTL 被删的总数
mem_fragmentation_ratio碎片率,长期 > 1.5 考虑重启或 activedefrag

evicted_keys 持续上涨说明上限太小或热点过多,要扩容或调策略。

下一篇

On this page