爲什麼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設計與實現》中的相關描述一致。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章