今天工作的时候,在set 新值时突然报错
(error) MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.
百度之,全是 config set stop-writes-on-bgsave-error no
Excuse me ???
抱着日乐购的感觉继续挖掘,终于在stackoverflow上看到了正解,点击阅读原文
首先
报错意思就是redis要进行持久化,把他那个rdb文件写入到硬盘里,但是现在因为某种问题写不了,报错了,也不让存储新值了
并且在rdb文件持续无法写入到系统时,你甚至无法关闭 重启它
这种持久化到硬盘的操作也可以手动来进行,命令如下
BGSAVE
造成持久化失败的原因有几种,
大致分为文件权限和内存俩方面
并且查看日志即可直接知道原因. 默认日志路径如下
/var/log/redis/redis-server.log
然后,我看到我的日志里,铺天盖地的
Failed opening .rdb for saving: Read-only file system
Background saving error
emmm ... 文件权限的问题
rdb文件的储存位置在redis.conf
配置文件中的dir
项中
/etc/redis/redis.conf
dir /var/lib/redis
这貌似是正常的 redis默认保存路径,去查看了下 权限果然没问题,用户组和用户也都是 redis,为啥会保存不了呢?
通过redis-cli
登录, 查看 配置 dir
项的值
config get dir
1) "dir"
2) "/var/spool/cron"
卧槽?/var/spool/cron
是个什么鬼目录。。查了下貌似是linux定时任务相关的,暂时先不管
修改之
config set dir /var/lib/redis
BGSAVE
退出,查看一下日志
RDB: 0 MB of memory used by copy-on-write
Background saving terminated with success
试一下重启
service redis-server restart
不错 都没啥问题了 不过dir的配置自己变了还真是个谜
然后
简单理解一下内存问题导致的持久化失败,因为我没遇到,简单看看别人的理解消化一下
Redis FAQ中关于持久化:
Redis的后台保存模式依赖于操作系统 fork 中的 copy-on-write(写时复制):Redis fork 一个子进程,他是父进程的精确副本,子进程把数据写到磁盘上,然后退出
这里redis创建的子进程所占用的内存理论上是和主进程一样的,即 8GB 的 Redis数据在持久化时,所需要的内存会直接翻倍,内存如果不足的话,即fork失败,持久化失败
以上是系统配置为 overcommit_memory = 0
时会发生的情况
实际上使用了copy-on-write语义,fork的子进程所需的内存是可以和主进程共享的,不需要完整的要写入磁盘大小的内存
系统配置为 overcommit_memory = 1
,允许系统积极分配物理内存
/etc/sysctl.conf
vm.overcommit_memory=1
sysctl -p
刷新系统后,重启redis,你会发现之前日志里如下的警告消失了
WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
到最后了
不得不吐槽一下 最开始百度到的stop-writes-on-bgsave-error no
到底是个啥
很简单 就是无视 无法持久化的错误,可以继续向redis里塞东西。然后你可能发现是可以继续用了,但是却不能把redis(关闭/重启)?