bigywater.tech
Redis · 108

Redis Lazy Free

大对象的内存释放是一个会阻塞主线程的操作:删掉一个大集合,别的客户端就得等。Lazy Free 把释放挪到后台线程。这篇不重复 DEL 与 UNLINK 的区别(第 19 篇),而是量各个 lazyfree 开关到底改变了什么,包括默认值(在这个版本上出乎意料)和「过期删除」这条容易被忽略的路径。

默认全是 no
本机 8.10.2 上所有 lazyfree-* 配置默认 no
165 → 0.7 ms
释放 200 万成员的集合:DEL(默认)→ UNLINK
213 → 0.5 ms
大 key 过期时另一个连接 PING 的最大停顿:lazy-expire no → yes

默认值

实测 · 本机执行输出
  lazyfree-lazy-user-del       no
  lazyfree-lazy-eviction       no
  lazyfree-lazy-expire         no
  lazyfree-lazy-server-del     no
  lazyfree-lazy-user-flush     no
  replica-lazy-flush           no

这个版本(8.10.2)上,所有相关的开关默认都是 no。也就是说不做任何配置时,DEL、过期删除、淘汰、清库都在主线程里同步释放内存。(不同版本的默认值可能不同,以 CONFIG GET 为准。)

DEL、UNLINK 与 lazy-user-del

实测 · 本机执行输出
方式                                                命令耗时     PING 最大停顿
  (集合已建好:SCARD = 2000000 ,used_memory 61 MB)
DEL(默认 lazyfree-lazy-user-del no)          165.0 ms       164.2 ms   lazyfreed_objects=0
UNLINK                                       0.7 ms         0.2 ms   lazyfreed_objects=1
DEL + lazyfree-lazy-user-del yes             0.4 ms         0.3 ms   lazyfreed_objects=2

200 万成员的集合(used_memory 约 61 MB)。默认 DEL:165 ms,另一个连接的 PING 停顿 164 ms;UNLINK 或者开了 lazyfree-lazy-user-del yes 的 DEL:不到 1 ms。INFO memory 里的 lazyfreed_objects 记录被后台释放的对象数。

FLUSHALL

实测 · 本机执行输出
  FLUSHALL           命令耗时   403.6 ms   PING 最大停顿     0.2 ms   lazyfree_pending_objects(命令刚返回后)见下
  FLUSHALL ASYNC     命令耗时     0.4 ms   PING 最大停顿     0.1 ms   lazyfree_pending_objects(命令刚返回后)见下

300 万个小 key:FLUSHALL 命令本身 404 ms,FLUSHALL ASYNC 0.4 ms。有意思的是,同步 FLUSHALL 期间另一个连接的 PING 停顿也只有 0.2 ms——说明清库不是一次性阻塞到底(我没有查是不是分批清空时处理了事件)。所以清库和删单个大 key 的阻塞形态不同。

过期:被忽略的一条路径

实测 · 本机执行输出
  lazyfree-lazy-expire no   3 秒观察期内 PING 最大停顿 212.8 ms;bigexp 是否还存在 = 0
  lazyfree-lazy-expire yes  3 秒观察期内 PING 最大停顿 0.5 ms;bigexp 是否还存在 = 0

给大集合设 500 ms 过期。lazyfree-lazy-expire no:到期时主线程同步释放,观察到另一个连接 PING 最大停顿 213 ms;yes:0.5 ms。这就是「大 key 过期造成周期性抖动」的来源(第 20、27 篇)。

分步演示:哪些操作会被异步化

Redis Lazy Free
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / Redis 8.10.2 独立实例(本机回环端口,save 关闭),redis-cli 风格输出由自写的 RESP 客户端打印;计时用 time.perf_counter,数字每次运行会有小幅抖动。集合 200 万成员;PING 每 0.5 ms 一次;每个配置一次测量(差别是几十倍,不需要重复)
    • 没有验证:lazyfree-lazy-eviction / lazyfree-lazy-server-del 的效果、replica-lazy-flush、后台释放线程本身占用 CPU 的代价、更大对象(GB 级)下的行为
    京ICP备2026067502号-1京公网安备11010502063487号