为什么redis不能保证100%数据不丢失

为什么redis不能保证100%数据不丢失

起因

  前段时间面试被问到,Redis能否保证100%数据不丢失,我回答不能。面试官又问,为什么呢?我一时语塞,慌忙回答因为异步写盘。
  随后我在百度上搜了搜,发现很多博客都讲,将appendfsync值设置为always就可以了。这回答让我对《redis设计与实现》产生了怀疑。难道新版本的redis能够保证数据100%不丢失?!
  搜不到答案,自己找答案好了,于是开始阅读redis源码。

准备环境

  1. 下载source insight4.0软件,阅读c代码很方便。
  2. 下载redis4源码,解压,源码位于src下
  3. 附上redis源码结构

阅读源码

  1. 按照知乎上的源码结构,并未找到redis.c,应该是server.c
  2. 打开server.c,找到main函数在这里插入图片描述
    main函数最后,有调用事件循环的函数
    在这里插入图片描述
    我们进入aeMain函数看下在这里插入图片描述
      可以看到,是一个while循环,我们把这个循环叫做事件循环。在循环中做了两件事情,分别是执行beforesleepaeProcessEvents方法。
      重点关注下beforesleep方法,具体的执行函数在server.c中被设置进来aeSetBeforeSleepProc(server.el,beforeSleep);。所以到server.c中搜索beforeSleep方法。在这里插入图片描述
    注释写的很详细,在函数末尾,有flushAppendOnlyFile(0);的调用,会将aof buffer写到磁盘上。看一看flushAppendOnlyFile方法:
    在这里插入图片描述
      我们读一读函数注释,大体意思就是:先把写命令追加到aof buffer中,下一次进入事件循环循环后,再将buffer写到磁盘上。
      结合while循环处方法的调用顺序,可以看出确实是这样的。那么也就是说,这次写到磁盘上的内容是上一个事件循环产生的。看下flushAppendOnlyFile完整的代码:
    在这里插入图片描述在这里插入图片描述
      注释很详细,在方法最后部分,有if (server.aof_fsync == AOF_FSYNC_ALWAYS)的判断,如果条件符合,会使用fdatasync()的方法来写磁盘。
      到这里,我们可以肯定,redis即使在配制appendfsync=always的策略下,还是会丢失一个事件循环的数据,与《redis设计与实现》中的相关描述一致。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章