Redis持久化配置不当导致磁盘满:自动归档与清理脚本

作者:技术拾光时间:2026-07-20 08:35:08浏览:70

Redis持久化不直接写满磁盘,RDB快照和AOF重写的大文件若缺乏清理机制会堆积磁盘空间。通过cron脚本归档旧文件、删除残留临时文件,并配置auto-aof-rewrite及appendfsynceverysec,可避免磁盘满。还需监控磁盘空闲、持久化状态及客户端连接数,预防失效风险。

很多人忽略了一个关键点:Redis持久化本身并不会直接导致磁盘写满,但RDB快照和AOF重写生成的文件很可能成为磁盘空间的“隐形杀手”。如果没有一套完善的归档与清理机制,旧文件堆积、AOF文件膨胀、或者bgsa ve失败后残留的临时文件,都会以惊人的速度吞噬磁盘空间。

Redis持久化配置不当导致磁盘满:自动归档与清理脚本

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

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

RDB快照从不会直接覆盖旧文件,而是先写入一个临时文件,再执行原子性的rename操作。AOF重写(bgrewriteaof)也是同样的逻辑。问题在于:如果进程异常退出、磁盘I/O延迟太高、或者配置了多个sa ve触发条件,就可能留下没写完的temp-*.rdb或appendonly.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 AOF或Can't open the temp AOF file

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

千万别指望Redis自身的清理逻辑能解决这个问题——它只管“当前活跃文件”,不管“历史备份”。必须靠外部脚本来控制文件的生命周期。核心原则很简单:只保留最近N个RDB外加最近1个AOF(重写后的),其余的全部压缩归档或直接删除。

  • 归档脚本示例(保存为/usr/local/bin/redis-cleanup.sh):
    #!/bin/bash
    REDIS_DATA="/var/lib/redis"
    DAYS_TO_KEEP=7
    ARCHIVE_DIR="/backup/redis/archive"
    
    mkdir -p "$ARCHIVE_DIR"
    
    # 归档老RDB(保留最新3个,其余tar.gz后移走)
    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" {}
    
    # 删除超过$DAYS_TO_KEEP天的归档包
    find "$ARCHIVE_DIR" -name "rdb-*.tar.gz" -mtime +$DAYS_TO_KEEP -delete
    
    # 强制清理残留temp文件
    find "$REDIS_DATA" -name "temp-*.rdb" -o -name "appendonly.aof.*" -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 yes
    auto-aof-rewrite-percentage 100
    auto-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_bgsa ve_status和redis_aof_last_rewrite_status:状态为err时立即通知运维,说明持久化已经失效
  • redis_connected_clients + redis_blocked_clients突增:这经常伴随bgsa ve fork失败(Cannot allocate memory错误),本质是系统内存不足导致fork失败,进而阻塞后续持久化,形成恶性循环

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