面試題:redis 的持久化有幾種?不同的持久化機制有什麼優缺點?

面試題

redis 的持久化有哪幾種方式?不同的持久化機制都有什麼優缺點?持久化機制具體底層是如何實現的?

面試官心理分析

redis 如果僅僅只是將數據緩存在內存裡面,如果 redis 宕機了再重啟,內存裡的數據就全部都弄丟了啊。你必須得用 redis 的持久化機制,將數據寫入內存的同時,異步的慢慢的將數據寫入磁盤文件裡,進行持久化。

如果 redis 宕機重啟,自動從磁盤上加載之前持久化的一些數據就可以了,也許會丟失少許數據,但是至少不會將所有數據都弄丟。

這個其實一樣,針對的都是 redis 的生產環境可能遇到的一些問題,就是 redis 要是掛了再重啟,內存裡的數據不就全丟了?能不能重啟的時候把數據給恢復了?

面試題剖析

持久化主要是做災難恢復、數據恢復,也可以歸類到高可用的一個環節中去,比如你 redis 整個掛了,然後 redis 就不可用了,你要做的事情就是讓 redis 變得可用,儘快變得可用。

重啟 redis,儘快讓它堆外提供服務,如果沒做數據備份,這時候 redis 啟動了,也不可用啊,數據都沒了。

很可能說,大量的請求過來,緩存全部無法命中,在 redis 里根本找不到數據,這個時候就死定了,出現緩存雪崩問題。所有請求沒有在 redis 命中,就會去 mysql 數據庫這種數據源頭中去找,一下子 mysql 承接高併發,然後就掛了...

如果你把 redis 持久化做好,備份和恢復方案做到企業級的程度,那麼即使你的 redis 故障了,也可以通過備份數據,快速恢復,一旦恢復立即對外提供服務。

redis 持久化的兩種方式

RDB:RDB 持久化機制,是對 redis 中的數據執行週期性的持久化。

AOF:AOF 機制對每條寫入命令作為日誌,以 append-only 的模式寫入一個日誌文件中,在 redis 重啟的時候,可以通過回放 AOF 日誌中的寫入指令來重新構建整個數據集。

通過 RDB 或 AOF,都可以將 redis 內存中的數據給持久化到磁盤上面來,然後可以將這些數據備份到別的地方去,比如說阿里雲等雲服務。

如果 redis 掛了,服務器上的內存和磁盤上的數據都丟了,可以從雲服務上拷貝回來之前的數據,放到指定的目錄中,然後重新啟動 redis,redis 就會自動根據持久化數據文件中的數據,去恢復內存中的數據,繼續對外提供服務。

如果同時使用 RDB 和 AOF 兩種持久化機制,那麼在 redis 重啟的時候,會使用 AOF 來重新構建數據,因為 AOF 中的數據更加完整。

RDB 優缺點

RDB會生成多個數據文件,每個數據文件都代表了某一個時刻中 redis 的數據,這種多個數據文件的方式,非常適合做冷備,可以將這種完整的數據文件發送到一些遠程的安全存儲上去,比如說 Amazon 的 S3 雲服務上去,在國內可以是阿里雲的 ODPS 分佈式存儲上,以預定好的備份策略來定期備份redis中的數據。

RDB 對 redis 對外提供的讀寫服務,影響非常小,可以讓 redis 保持高性能,因為 redis 主進程只需要 fork 一個子進程,讓子進程執行磁盤 IO 操作來進行 RDB 持久化即可。

相對於 AOF 持久化機制來說,直接基於 RDB 數據文件來重啟和恢復 redis 進程,更加快速。

如果想要在 redis 故障時,儘可能少的丟失數據,那麼 RDB 沒有 AOF 好。一般來說,RDB 數據快照文件,都是每隔 5 分鐘,或者更長時間生成一次,這個時候就得接受一旦 redis 進程宕機,那麼會丟失最近 5 分鐘的數據。

RDB 每次在 fork 子進程來執行 RDB 快照數據文件生成的時候,如果數據文件特別大,可能會導致對客戶端提供的服務暫停數毫秒,或者甚至數秒。

AOF 優缺點

AOF 可以更好的保護數據不丟失,一般 AOF 會每隔 1 秒,通過一個後臺線程執行一次fsync操作,最多丟失 1 秒鐘的數據。

AOF 日誌文件以 append-only 模式寫入,所以沒有任何磁盤尋址的開銷,寫入性能非常高,而且文件不容易破損,即使文件尾部破損,也很容易修復。

AOF 日誌文件即使過大的時候,出現後臺重寫操作,也不會影響客戶端的讀寫。因為在 rewrite log 的時候,會對其中的指導進行壓縮,創建出一份需要恢復數據的最小日誌出來。再創建新日誌文件的時候,老的日誌文件還是照常寫入。當新的 merge 後的日誌文件 ready 的時候,再交換新老日誌文件即可。

AOF 日誌文件的命令通過非常可讀的方式進行記錄,這個特性非常適合做災難性的誤刪除的緊急恢復。比如某人不小心用 flushall 命令清空了所有數據,只要這個時候後臺 rewrite 還沒有發生,那麼就可以立即拷貝 AOF 文件,將最後一條 flushall 命令給刪了,然後再將該 AOF 文件放回去,就可以通過恢復機制,自動恢復所有數據。

對於同一份數據來說,AOF 日誌文件通常比 RDB 數據快照文件更大。

AOF 開啟後,支持的寫 QPS 會比 RDB 支持的寫 QPS 低,因為 AOF 一般會配置成每秒 fsync 一次日誌文件,當然,每秒一次 fsync,性能也還是很高的。(如果實時寫入,那麼 QPS 會大降,redis 性能會大大降低)

以前 AOF 發生過 bug,就是通過 AOF 記錄的日誌,進行數據恢復的時候,沒有恢復一模一樣的數據出來。所以說,類似 AOF 這種較為複雜的基於命令日誌/merge/回放的方式,比基於 RDB 每次持久化一份完整的數據快照文件的方式,更加脆弱一些,容易有 bug。不過 AOF 就是為了避免 rewrite 過程導致的 bug,因此每次 rewrite 並不是基於舊的指令日誌進行 merge 的,而是基於當時內存中的數據進行指令的重新構建,這樣健壯性會好很多。

RDB和AOF到底該如何選擇

不要僅僅使用 RDB,因為那樣會導致你丟失很多數據

也不要僅僅使用 AOF,因為那樣有兩個問題,第一,你通過 AOF 做冷備,沒有 RDB 做冷備,來的恢復速度更快; 第二,RDB 每次簡單粗暴生成數據快照,更加健壯,可以避免 AOF 這種複雜的備份和恢復機制的 bug。

redis 支持同時開啟開啟兩種持久化方式,我們可以綜合使用 AOF 和 RDB 兩種持久化機制,用 AOF 來保證數據不丟失,作為數據恢復的第一選擇; 用 RDB 來做不同程度的冷備,在 AOF 文件都丟失或損壞不可用的時候,還可以使用 RDB 來進行快速的數據恢復。

相關推薦

推薦中...