Redis "MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on di

转载 2016年06月01日 18:34:53

碰到一个悲催的事情:一台Redis服务器,4核,16G内存且没有任何硬件上的问题。持续高压运行了大约3个月,保存了大约14G的数据,设置了比较完备的Save参数。而就是这台主机,在一次重起之后,丢失了大量的数据,14G的数据最终只恢复了几百兆而已。

正常情况下,像Redis这样定期回写磁盘的内存数据库,丢失几个数据也是在情理之中,可超过80%数据丢失率实在太离谱。排除了误操作的可能性之后,开始寻找原因。

重启动时的日志:

[26641] 21 Dec 09:46:34 * Slave ask for synchronization

[26641] 21 Dec 09:46:34 * Starting BGSAVE for SYNC

[26641] 21 Dec 09:46:34 # Can’t save in background: fork: Cannot allocate memory

[26641] 21 Dec 09:46:34 * Replication failed, can’t BGSAVE

[26641] 21 Dec 09:46:34 # Received SIGTERM, scheduling shutdown…

[26641] 21 Dec 09:46:34 # User requested shutdown…

很明显的一个问题,系统不能在后台保存,fork进程失败。

翻查了几个月的日志,发觉系统在频繁报错:

[26641] 18 Dec 04:02:14 * 1 changes in 900 seconds. Saving…

[26641] 18 Dec 04:02:14 # Can’t save in background: fork: Cannot allocate memory

系统不能在后台保存,fork进程时无法指定内存。

对源码进行跟踪,在src/rdb.c中定位了这个报错:

int rdbSaveBackground(char *filename) {
    pid_t childpid;
    long long start;

    if (server.bgsavechildpid != -1) return REDIS_ERR;
    if (server.vm_enabled) waitEmptyIOJobsQueue();
    server.dirty_before_bgsave = server.dirty;
    start = ustime();
    if ((childpid = fork()) == 0) {
        /* Child */
        if (server.vm_enabled) vmReopenSwapFile();
        if (server.ipfd > 0) close(server.ipfd);
        if (server.sofd > 0) close(server.sofd);
        if (rdbSave(filename) == REDIS_OK) {
            _exit(0);
        } else {
            _exit(1);
        }
    } else {
        /* Parent */
        server.stat_fork_time = ustime()-start;
        if (childpid == -1) {
            redisLog(REDIS_WARNING,"Can't save in background: fork: %s",
                strerror(errno));
            return REDIS_ERR;
        }
        redisLog(REDIS_NOTICE,"Background saving started by pid %d",childpid);
        server.bgsavechildpid = childpid;
        updateDictResizePolicy();
        return REDIS_OK;
    }
    return REDIS_OK; /* unreached */
}

数据丢失的问题总算搞清楚了!

Redis的数据回写机制分同步和异步两种,

  1. 同步回写即SAVE命令,主进程直接向磁盘回写数据。在数据大的情况下会导致系统假死很长时间,所以一般不是推荐的。
  2. 异步回写即BGSAVE命令,主进程fork后,复制自身并通过这个新的进程回写磁盘,回写结束后新进程自行关闭。由于这样做不需要主进程阻塞,系统不会假死,一般默认会采用这个方法。

个人感觉方法2采用fork主进程的方式很拙劣,但似乎是唯一的方法。内存中的热数据随时可能修改,要在磁盘上保存某个时间的内存镜像必须要冻结。冻结就会导致假死。fork一个新的进程之后等于复制了当时的一个内存镜像,这样主进程上就不需要冻结,只要子进程上操作就可以了。

在小内存的进程上做一个fork,不需要太多资源,但当这个进程的内存空间以G为单位时,fork就成为一件很恐怖的操作。何况在16G内存的主机上fork 14G内存的进程呢?肯定会报内存无法分配的。更可气的是,越是改动频繁的主机上fork也越频繁,fork操作本身的代价恐怕也不会比假死好多少。

找到原因之后,直接修改内核参数vm.overcommit_memory = 1

Linux内核会根据参数vm.overcommit_memory参数的设置决定是否放行。

  1.  如果 vm.overcommit_memory = 1,直接放行
  2. vm.overcommit_memory = 0:则比较 此次请求分配的虚拟内存大小和系统当前空闲的物理内存加上swap,决定是否放行。
  3. vm.overcommit_memory = 2:则会比较 进程所有已分配的虚拟内存加上此次请求分配的虚拟内存和系统当前的空闲物理内存加上swap,决定是否放行。

相关文章推荐

MISCONF Redis is configured to save RDB snapshots

今天在redis中执行setrange name 1 chun 命令时报了如下错误提示:

读取redis中的数据时出现:MISCONF Redis is configured to save RDB snapshots

以下为异常详细信息:Exception in thread "main" redis.clients.jedis.exceptions.JedisDataException: MISCONF Redi...

MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk.

晚上10点,同事给我电话,服务器挂掉了,报错如下:   File "build\bdist.win32\egg\redis\client.py", line 361, in execute_comm...

redis异常解决:MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist

项目中用到redis做缓存服务器,近日出现这个异常: redis.clients.jedis.exceptions.JedisDataException: MISCONF Redis is conf...

Redis Error --MISCONF Redis is configured to save RDB snapshots省略

1,MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. C...

Redis "MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on di

http://www.redicecn.com/html/Linux/20131125/468.html 今天第二次遇到Redis “MISCONF Redis is configured ...
  • cdnight
  • cdnight
  • 2014年02月27日 20:46
  • 1365

redis 问题解决(MISCONF Redis is configured to save RDB snapshots)

(error) MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on d...

Redis提示(error) MISCONF Redis is configured to save RDB snapshots, but it is currently not able to pe

1.Redis登录进去显示如下错误提示: (error) MISCONF Redis is configured to save RDB snapshots, but it is currently ...

redis error MISCONF Redis is configured to save RDB snapshots

1 redis 127.0.0.1:6379> sadd myset "hello" (error) MISCONF Redis is configured to save RDB snaps...

解决保存快照失败后redis无法写入的问题

用命令行工具连上后执行“set test 0”出现以下错误提示: MISCONF Redis is configured to save RDB snapshots, but is currentl...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Redis "MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on di
举报原因:
原因补充:

(最多只允许输入30个字)