如何解决Redis因持久化配置不当导致的磁盘满_配置自动归档与清理脚本

作者:袖梨 2026-07-11
Redis持久化本身不直接写满磁盘,但RDB快照和AOF重写生成大文件,若缺乏归档与清理机制,旧文件堆积、AOF膨胀或bgsave失败残留临时文件,会迅速耗尽磁盘空间。

Redis 持久化本身不直接写满磁盘,但 RDB 快照和 AOF 重写会生成大文件,若缺乏归档与清理机制,旧文件堆积、AOF 膨胀、或 bgsave 失败残留临时文件,就会迅速耗尽磁盘空间。

为什么 RDB/AOF 文件会越积越多

RDB 不是覆盖写,而是先写临时文件再原子 rename;AOF 重写(bgrewriteaof)同理。若进程异常退出、磁盘 I/O 延迟高、或配置了多个 save 触发条件,就可能留下未完成的 temp-*.rdbappendonly.aof.tmp。更隐蔽的是:AOF 文件在重写后不会自动删除旧文件,需等新文件完全写入并切换后才由 Redis 主动 unlink —— 这个窗口期若发生 OOM 或 kill -9,旧 AOF 就卡住不删。

  • 检查残留文件:ls -lh /var/lib/redis/*.rdb /var/lib/redis/appendonly.aof*
  • 确认是否有多份历史快照:find /var/lib/redis -name "*.rdb" -mmin +1440(查 24 小时前的)
  • AOF 重写失败日志通常出现在 redis-server.log 中,关键词是 Failed to rewrite the AOFCan't open the temp AOF file

用 cron + shell 脚本实现自动归档与清理

不要依赖 Redis 自身的清理逻辑,它只管“当前活跃文件”,不管“历史备份”。必须用外部脚本控制生命周期。关键原则:只保留最近 N 个 RDB + 最近 1 个 AOF(重写后),其余全部压缩归档或删除。

  • 归档脚本示例(保存为 /usr/local/bin/redis-cleanup.sh):
    #!/bin/bashREDIS_DATA="/var/lib/redis"DAYS_TO_KEEP=7ARCHIVE_DIR="/backup/redis/archive"<p>mkdir -p "$ARCHIVE_DIR"</p><h1>归档老 RDB(保留最新 3 个,其余 tar.gz 后移走)</h1><p>ls -t "$REDIS_DATA"/*.rdb 2>/dev/null | tail -n +4 | xargs -r -I{} tar -czf "$ARCHIVE_DIR/rdb-$(date -d @$(stat -c %Y {}) +%Y%m%d-%H%M%S).tar.gz" {}</p><div class="aritcle_card flexRow">                                                        <div class="artcardd flexRow">                                                                <a class="aritcle_card_img" href="/xiazai/gongju/2199" title="Redis 8.2.3"><img                                                                                src="https://img.php.cn/upload/manual/001/589/237/69f31fe8b56d4731.png" alt="Redis 8.2.3"  onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>                                                                <div class="aritcle_card_info flexColumn">                                                                        <a href="/xiazai/gongju/2199" title="Redis 8.2.3">Redis 8.2.3</a>                                                                        <p>Redis 8.2.3 是一款安全优先的高性能键值存储系统。该版本紧急修复了可能引发远程代码执行(RCE)的高危漏洞(CVE-2025-62507),并解决了 HyperLogLog 及 Cuckoo Filter 等数据结构在特定场景下的崩溃问题。建议所有用户立即升级,以保障生产环境的系统稳定与数据安全。</p>                                                                </div>                                                                <a href="/xiazai/gongju/2199" title="Redis 8.2.3" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a>                                                        </div>                                                </div><h1>删除超过 $DAYS_TO_KEEP 天的归档包</h1><p>find "$ARCHIVE_DIR" -name "rdb-*.tar.gz" -mtime +$DAYS_TO_KEEP -delete</p><h1>强制清理残留 temp 文件</h1><p>find "$REDIS_DATA" -name "temp-<em>.rdb" -o -name "appendonly.aof.</em>" -delete
  • 加执行权限:chmod +x /usr/local/bin/redis-cleanup.sh
  • 加入 crontab(每天凌晨 2 点运行):0 2 * * * /usr/local/bin/redis-cleanup.sh >> /var/log/redis-cleanup.log 2>&1

避免 AOF 无限膨胀的配置组合

AOF 文件大小失控是磁盘满最常见诱因。单纯设 auto-aof-rewrite-percentage 不够,必须配合硬性截断和重写保护。

  • redis.conf 中启用以下三项:
    appendonly yesauto-aof-rewrite-percentage 100auto-aof-rewrite-min-size 64mb
  • 但关键补充:设置 aof-rewrite-incremental-fsync yes(默认开启),减少重写时的 I/O 峰值;同时确保 no-appendfsync-on-rewrite yes,避免 AOF fsync 和重写同时争抢磁盘
  • 禁止使用 appendfsync always:它让每次写都落盘,在高写入场景下极易压垮磁盘吞吐,改用 everysec 是平衡安全与性能的底线

监控与告警必须覆盖的三个硬指标

光靠脚本清理是被动防御。磁盘满之前,一定有可观察的征兆。以下三个指标必须接入 Prometheus/Grafana 或 Zabbix:

  • disk_free(挂载点空闲空间):低于 20% 触发 P1 告警,低于 10% 自动触发紧急清理脚本
  • redis_rdb_last_bgsave_statusredis_aof_last_rewrite_status:状态为 err 时立即通知运维,说明持久化已失效
  • redis_connected_clients + redis_blocked_clients 突增:常伴随 bgsave fork 失败(Cannot allocate memory 错误),本质是系统内存不足导致 fork 失败,进而阻塞后续持久化,形成恶性循环

真正危险的不是“磁盘满了”,而是“磁盘快满时 Redis 还在拼命写 AOF、同时 fork 不出子进程、又拒绝淘汰 key”——这个三重叠加状态,必须靠组合监控提前掐断。

相关文章

精彩推荐