memcached 的 flush_all 命令用于 立即清空整个缓存(所有 key-value 数据),是 最危险但最直接的运维命令。
命令格式
flush_all [delay]
| 参数 | 说明 |
|---|---|
| 无参数 | 立即 失效所有 item(逻辑删除,内存稍后回收) |
delay | 延迟 N 秒后 失效所有 item(整数,单位:秒) |
协议交互示例(telnet / nc):
flush_all
OK
flush_all 30
OK
工作原理(重要!)
- 不是物理删除:
- 不会立刻释放内存
- 只是 标记所有 item 为“已过期”(设置过期时间为当前时间)
- 内存回收时机:
- 写新数据时:复用已过期 item 的 chunk(
stats items中的reclaimed增加) - LRU 淘汰时:被驱逐
- crawler 主动回收:需启用
-o crawl(后台线程)
- 延迟执行(
flush_all 30):
- 在未来 30 秒内,所有 新写入的 item 也会被立即标记过期
- 适合“滚动重启”或“灰度发布”场景
响应输出
| 响应 | 含义 |
|---|---|
OK | 命令已接受,计划执行 |
ERROR | 语法错误(如 flush_all abc) |
配合其他命令使用
| 命令 | 用途 |
|---|---|
stats | 查看 total_items、curr_items、evictions、reclaimed |
stats items | 查看 reclaimed 计数(过期 item 被复用次数) |
stats slabs | 查看 free_chunks_end 增加(可回收空间) |
实用场景与技巧
1. 紧急清缓存(生产慎用!)
echo "flush_all" | nc 127.0.0.1 11211
后果:所有缓存失效 → 缓存雪崩 → DB 压力暴增
安全做法:
# 延迟 60 秒清空,给应用预热时间
echo "flush_all 60" | nc 127.0.0.1 11211
2. 滚动重启多实例(推荐)
# 实例1
echo "flush_all 120" | nc 127.0.0.1 11211
# 等待 30 秒,启动新进程
sleep 30
systemctl restart memcached@1
# 实例2 重复...
保证在 120 秒内,旧数据逐步失效,新实例逐步预热
3. 验证是否生效
# 清空前
stats | grep curr_items
# → curr_items 123456
# 执行 flush_all
echo "flush_all" | nc 127.0.0.1 11211
# 清空后(立即)
stats | grep curr_items
# → curr_items 0 (逻辑上已清空)
# 内存不会立刻下降,观察 reclaimed
watch -n1 'stats items | grep reclaimed'
4. 配合 crawler 强制回收内存
# 启动时启用 crawler
memcached -o crawl
# 手动触发一次爬取(协议不支持,需重启或等待)
# 或设置自动间隔(1.6+ 支持)
常见问题与误区
| 问题 | 原因 | 解决 |
|---|---|---|
flush_all 后内存没下降 | 只是标记过期,内存待复用 | 写新数据或重启 |
flush_all 30 后新写数据立即丢失 | 延迟窗口内所有写操作都失效 | 避免使用,或改用 flush_all 无延迟 |
多实例同时 flush_all 引发雪崩 | 所有节点同时失效 | 错峰执行,或用延迟 |
curr_items 降为 0 但 get 还能命中 | 旧连接未释放 | 等待连接关闭或重启客户端 |
替代方案(推荐生产使用)
| 方案 | 优点 | 实现 |
|---|---|---|
| 带 TTL 的 key | 自动过期,无需手动 | set key 0 300 ... |
| 分版本前缀 | 逻辑隔离,精准清空 | v1:user:123, v2:user:123 |
| 多实例 + 一致性哈希 | 局部失效 | 客户端路由 |
| Lua 脚本 + 标记删除 | 软删除 | 自定义协议 |
协议级实现(telnet 示例)
telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
flush_all
OK
flush_all 60
OK
quit
客户端库支持
| 语言 | 示例 |
|---|---|
| Python (pymemcache) | client.flush_all(delay=60) |
| PHP | $mem->flush(60); |
| Java (spymemcached) | memcachedClient.flush(60); |
| Go | client.Flush(context.Background(), 60) |
监控建议
# 监控 flush_all 触发
watch -n1 "stats | grep -E 'cmd_flush|curr_items|reclaimed'"
# 输出示例
STAT cmd_flush 5
STAT curr_items 0
STAT reclaimed 123456
cmd_flush累计执行次数,可用于告警
官方文档
总结
| 项目 | 内容 |
|---|---|
| 命令 | flush_all [delay] |
| 作用 | 逻辑清空缓存(标记过期) |
| 内存释放 | 延迟释放(靠写新数据或 crawler) |
| 风险 | 缓存雪崩、DB 打挂 |
| 最佳实践 | 加延迟 + 滚动执行 + 监控 reclaimed |
| 替代方案 | TTL、前缀版本、多实例 |
紧急情况下的安全操作模板:
# 1. 延迟清空(给应用 2 分钟预热)
echo "flush_all 120" | nc 127.0.0.1 11211
# 2. 监控 reclaimed 上升
watch -n5 "stats items | grep -E 'reclaimed|crawler_reclaimed'"
# 3. 确认业务恢复后,重启实例
systemctl restart memcached
需要我帮你写一个“安全 flush_all”脚本?
可以包含:
- 延迟参数
- 确认提示
- 监控 reclaimed
- 多实例支持
- 日志记录
直接告诉我你的场景(单机/集群、生产/测试),我立刻生成!