解决Redis报错Redis is configured to save RDB snapshots, but it's currently unable to persist to disk.
前言
今天我们公司系统突然请求不了数据📊,回去发现服务没有问题,经过排查日志发现报了如下错误:
MISCONF Redis is configured to save RDB snapshots, but it's currently unable to persist to disk. Commands that may modify the data set are disabled, because this instance is configured to report errors during writes if RDB snapshotting fails (stop-writes-on-bgsave-error option). Please check the Redis logs for details about the RDB error
因为 Redis RDB 快照持久化(默认启用),在尝试保存快照到磁盘时失败,触发了 stop-writes-on-bgsave-error 保护机制。此时 Redis 会拒绝所有写入操作,可能的原因有:
- 磁盘空间不足
RDB 快照需要写入磁盘,如果磁盘空间已满,保存会失败。 - 目录权限问题
Redis 进程没有权限写入配置的 RDB 文件目录(默认 /var/lib/redis)。 - 内存不足导致 fork 失败
在生成 RDB 快照时,Redis 会 fork() 子进程。如果系统内存不足或内核参数限制(如 overcommit_memory 配置不当),会导致 fork 失败。 - 磁盘 I/O 性能问题
磁盘响应缓慢或故障,导致 RDB 文件写入超时。
解决方案
1. 检查磁盘空间
如果磁盘已满,清理无用文件(如日志、临时文件等)。
2. 检查目录权限
确保 Redis 进程有权写入 RDB 文件目录:
如果权限不足,修复目录权限:
3. 调整内存分配策略
如果日志中出现 Cannot allocate memory 错误,需修改内核参数 vm.overcommit_memory:
参数说明:vm.overcommit_memory=1 允许内核超额分配内存,避免 fork 失败。
4. 检查 Redis 日志
查看 Redis 日志获取具体错误信息(日志路径由 redis.conf 中的 logfile 指定):
5. 临时恢复写入(应急)
如果需紧急恢复写入,可临时关闭 stop-writes-on-bgsave-error 选项:
⚠️ 注意:此操作可能导致数据不一致,仅作为临时措施,需尽快解决根本问题!
6. 优化 RDB 配置
在 redis.conf 中调整 RDB 保存策略以减少频繁快照:
7. 改用 AOF 持久化(可选)
如果 RDB 问题难以解决,可启用 AOF(Append-Only File)持久化:
验证修复
手动触发 RDB 快照:
检查 RDB 文件是否生成:
我的解决
以上解决方案均出自 牛牛AI ,即本站新上线的免费AI
我尝试了第一种方法使用 df -h 命令查看磁盘占用情况,结果是磁盘空间已经占满;至此我就基本确定是因为磁盘空间不足导致redis rdb写入失败
发现都是 docker 相关的占用最多,于是我去查看了docker的占用情况
我的镜像和容器的占用不至于把磁盘给占满啊,于是我又去查了一番看一看overlay里面到底是什么东西。发现是 Docker 默认使用的存储驱动目录(overlay2),用于管理容器和镜像还有日志文件的。
首先容器和镜像我们已经在上图查看得到占用并不算大,那就剩下日志文件了,容器的日志在 /var/lib/docker/containers/ 下
于是我就去看,发现好几个占用 5GB 以上👀,还发现有一个容器的日志占了 23GB 多的日志😱。
这种情况是容器长时间运行,打印了大量的日志,占据了大量磁盘空间。这种情况下首先得清理日志文件,先保证服务正常。但这只是治标不治本,于是我就打算弄一个定时任务,定期清理容器内的日志,避免时间长了后会大量占用。
使用 truncate(centos自带)开启一个定时任务,命令如下:
解析:
- 0 0 * * *: cron表达式,表示每天凌晨 0 点执行。
- truncate -s 0: 将文件大小截断为 0 字节(清空文件内容,但保留文件句柄)。
- /var/lib/docker/containers/*/*-json.log: 匹配所有容器的 JSON 格式日志文件。