FLUSHALL 同步清空会阻塞 Redis 主线程数秒至数十秒,导致命令排队、监控告警;FLUSHALL ASYNC 由后台线程异步删除,主线程立即返回,但内存不立即释放、不支持并发执行,且不清理 AOF/RDB 残留。

FLUSHALL 同步清空为什么会让 Redis 卡住
执行 FLUSHALL 默认是同步操作:Redis 主线程会逐个遍历所有 key,释放内存、清理元数据、更新统计信息。当数据库里有几百万甚至上千万 key(尤其带大 value 或复杂结构如 Hash、ZSet),这个过程可能持续数秒到数十秒——期间所有命令都会排队等待,INFO stats 中的 total_commands_processed 几乎停滞,客户端超时、监控告警、服务雪崩都可能发生。
FLUSHALL ASYNC 真的不阻塞主线程吗
是的,但仅限于“主线程不参与实际删除”。FLUSHALL ASYNC 会把 key 的元数据(比如 dictEntry 指针)批量移交到一个后台线程(bio_close_file 线程池中的一个),由它异步遍历并释放内存。主线程立刻返回,redis-cli 显示 OK,命令队列恢复流动。
但要注意:
- 内存不会立刻下降:已删除的 key 占用的内存仍被后台线程持有,直到它完成释放;
INFO memory中的used_memory在后台线程跑完前基本不变 - 后台线程是单线程处理:如果 key 总量极大(比如 5000 万+),它可能持续运行几分钟,期间无法再触发另一次
FLUSHALL ASYNC(会报错ERR FLUSHALL ASYNC is already running) - 它不释放 AOF 缓冲区或 RDB 文件残留:如果开启了 AOF,清空后写入的
FLUSHALL命令仍留在 aof_buf 里;RDB 文件未重写前,旧数据还在磁盘上
清空前必须确认的三件事
别只盯着“快”,先保数据和业务安全:
- 确认当前连接的是目标库:用
SELECT 0或INFO server查db0:的keys=数量,避免在生产db0上误清db1 - 检查是否启用了 AOF +
appendfsync always:这种配置下,FLUSHALL ASYNC虽不卡主线程,但 AOF 日志写入仍会成为瓶颈,建议临时改为appendfsync everysec再执行 - 确认没有关键 key 设置了过期时间但尚未淘汰:
FLUSHALL会无视 TTL,一并清除;若依赖EXPIRE自动清理,应改用SCAN+DEL分批删
更稳妥的替代方案:分批清空 + 监控落地
对线上核心实例,优先考虑可控性而非绝对速度:
- 用
SCAN游标分批获取 key:SCAN 0 MATCH * COUNT 1000,每次最多处理 1000 个,避免单次命令耗时过长 - 用
DEL批量删除:DEL key1 key2 ... key1000,比逐个DEL效率高,且可捕获部分失败(如某些 key 已被其他进程删掉) - 每删一批,查一次
INFO memory的used_memory_peak和mem_fragmentation_ratio,确认内存真正回收、碎片没恶化 - 删完后手动触发
MEMORY PURGE(Redis 6.2+)或CONFIG RESETSTAT清理内部计数器
真正麻烦的不是“怎么删得快”,而是删完之后发现 used_memory 没降、latency spikes 反而变多——那大概率是后台线程还没收尾,或者内存分配器(jemalloc)碎片卡住了。这时候看 INFO memory 比反复敲 FLUSHALL ASYNC 有用得多。











