redis 的持久化有哪幾種方式?不同的持久化機(jī)制都有什么優(yōu)缺點(diǎn)?持久化機(jī)制具體底層是如何實(shí)現(xiàn)的?

原文出處:https://github.com/doocs/advanced-java/blob/master/docs/high-concurrency/redis-persistence.md
歡迎 star 關(guān)注 GitHub 項(xiàng)目最新動(dòng)態(tài)!

面試題

redis 的持久化有哪幾種方式?不同的持久化機(jī)制都有什么優(yōu)缺點(diǎn)?持久化機(jī)制具體底層是如何實(shí)現(xiàn)的?

面試官心理分析

redis 如果僅僅只是將數(shù)據(jù)緩存在內(nèi)存里面,如果 redis 宕機(jī)了再重啟,內(nèi)存里的數(shù)據(jù)就全部都弄丟了啊。你必須得用 redis 的持久化機(jī)制,將數(shù)據(jù)寫(xiě)入內(nèi)存的同時(shí),異步的慢慢的將數(shù)據(jù)寫(xiě)入磁盤(pán)文件里,進(jìn)行持久化。

如果 redis 宕機(jī)重啟,自動(dòng)從磁盤(pán)上加載之前持久化的一些數(shù)據(jù)就可以了,也許會(huì)丟失少許數(shù)據(jù),但是至少不會(huì)將所有數(shù)據(jù)都弄丟。

這個(gè)其實(shí)一樣,針對(duì)的都是 redis 的生產(chǎn)環(huán)境可能遇到的一些問(wèn)題,就是 redis 要是掛了再重啟,內(nèi)存里的數(shù)據(jù)不就全丟了?能不能重啟的時(shí)候把數(shù)據(jù)給恢復(fù)了?

面試題剖析

持久化主要是做災(zāi)難恢復(fù)、數(shù)據(jù)恢復(fù),也可以歸類(lèi)到高可用的一個(gè)環(huán)節(jié)中去,比如你 redis 整個(gè)掛了,然后 redis 就不可用了,你要做的事情就是讓 redis 變得可用,盡快變得可用。

重啟 redis,盡快讓它對(duì)外提供服務(wù),如果沒(méi)做數(shù)據(jù)備份,這時(shí)候 redis 啟動(dòng)了,也不可用啊,數(shù)據(jù)都沒(méi)了。

很可能說(shuō),大量的請(qǐng)求過(guò)來(lái),緩存全部無(wú)法命中,在 redis 里根本找不到數(shù)據(jù),這個(gè)時(shí)候就死定了,出現(xiàn)緩存雪崩問(wèn)題。所有請(qǐng)求沒(méi)有在 redis 命中,就會(huì)去 mysql 數(shù)據(jù)庫(kù)這種數(shù)據(jù)源頭中去找,一下子 mysql 承接高并發(fā),然后就掛了...

如果你把 redis 持久化做好,備份和恢復(fù)方案做到企業(yè)級(jí)的程度,那么即使你的 redis 故障了,也可以通過(guò)備份數(shù)據(jù),快速恢復(fù),一旦恢復(fù)立即對(duì)外提供服務(wù)。

redis 持久化的兩種方式

  • RDB:RDB 持久化機(jī)制,是對(duì) redis 中的數(shù)據(jù)執(zhí)行周期性的持久化。
  • AOF:AOF 機(jī)制對(duì)每條寫(xiě)入命令作為日志,以 append-only 的模式寫(xiě)入一個(gè)日志文件中,在 redis 重啟的時(shí)候,可以通過(guò)回放 AOF 日志中的寫(xiě)入指令來(lái)重新構(gòu)建整個(gè)數(shù)據(jù)集。

通過(guò) RDB 或 AOF,都可以將 redis 內(nèi)存中的數(shù)據(jù)給持久化到磁盤(pán)上面來(lái),然后可以將這些數(shù)據(jù)備份到別的地方去,比如說(shuō)阿里云等云服務(wù)。

如果 redis 掛了,服務(wù)器上的內(nèi)存和磁盤(pán)上的數(shù)據(jù)都丟了,可以從云服務(wù)上拷貝回來(lái)之前的數(shù)據(jù),放到指定的目錄中,然后重新啟動(dòng) redis,redis 就會(huì)自動(dòng)根據(jù)持久化數(shù)據(jù)文件中的數(shù)據(jù),去恢復(fù)內(nèi)存中的數(shù)據(jù),繼續(xù)對(duì)外提供服務(wù)。

如果同時(shí)使用 RDB 和 AOF 兩種持久化機(jī)制,那么在 redis 重啟的時(shí)候,會(huì)使用 AOF 來(lái)重新構(gòu)建數(shù)據(jù),因?yàn)?AOF 中的數(shù)據(jù)更加完整

RDB 優(yōu)缺點(diǎn)

  • RDB 會(huì)生成多個(gè)數(shù)據(jù)文件,每個(gè)數(shù)據(jù)文件都代表了某一個(gè)時(shí)刻中 redis 的數(shù)據(jù),這種多個(gè)數(shù)據(jù)文件的方式,非常適合做冷備,可以將這種完整的數(shù)據(jù)文件發(fā)送到一些遠(yuǎn)程的安全存儲(chǔ)上去,比如說(shuō) Amazon 的 S3 云服務(wù)上去,在國(guó)內(nèi)可以是阿里云的 ODPS 分布式存儲(chǔ)上,以預(yù)定好的備份策略來(lái)定期備份 redis 中的數(shù)據(jù)。

  • RDB 對(duì) redis 對(duì)外提供的讀寫(xiě)服務(wù),影響非常小,可以讓 redis 保持高性能,因?yàn)?redis 主進(jìn)程只需要 fork 一個(gè)子進(jìn)程,讓子進(jìn)程執(zhí)行磁盤(pán) IO 操作來(lái)進(jìn)行 RDB 持久化即可。

  • 相對(duì)于 AOF 持久化機(jī)制來(lái)說(shuō),直接基于 RDB 數(shù)據(jù)文件來(lái)重啟和恢復(fù) redis 進(jìn)程,更加快速。

  • 如果想要在 redis 故障時(shí),盡可能少的丟失數(shù)據(jù),那么 RDB 沒(méi)有 AOF 好。一般來(lái)說(shuō),RDB 數(shù)據(jù)快照文件,都是每隔 5 分鐘,或者更長(zhǎng)時(shí)間生成一次,這個(gè)時(shí)候就得接受一旦 redis 進(jìn)程宕機(jī),那么會(huì)丟失最近 5 分鐘的數(shù)據(jù)。

  • RDB 每次在 fork 子進(jìn)程來(lái)執(zhí)行 RDB 快照數(shù)據(jù)文件生成的時(shí)候,如果數(shù)據(jù)文件特別大,可能會(huì)導(dǎo)致對(duì)客戶端提供的服務(wù)暫停數(shù)毫秒,或者甚至數(shù)秒。

AOF 優(yōu)缺點(diǎn)

  • AOF 可以更好的保護(hù)數(shù)據(jù)不丟失,一般 AOF 會(huì)每隔 1 秒,通過(guò)一個(gè)后臺(tái)線程執(zhí)行一次fsync操作,最多丟失 1 秒鐘的數(shù)據(jù)。
  • AOF 日志文件以 append-only 模式寫(xiě)入,所以沒(méi)有任何磁盤(pán)尋址的開(kāi)銷(xiāo),寫(xiě)入性能非常高,而且文件不容易破損,即使文件尾部破損,也很容易修復(fù)。
  • AOF 日志文件即使過(guò)大的時(shí)候,出現(xiàn)后臺(tái)重寫(xiě)操作,也不會(huì)影響客戶端的讀寫(xiě)。因?yàn)樵?rewrite log 的時(shí)候,會(huì)對(duì)其中的指令進(jìn)行壓縮,創(chuàng)建出一份需要恢復(fù)數(shù)據(jù)的最小日志出來(lái)。在創(chuàng)建新日志文件的時(shí)候,老的日志文件還是照常寫(xiě)入。當(dāng)新的 merge 后的日志文件 ready 的時(shí)候,再交換新老日志文件即可。
  • AOF 日志文件的命令通過(guò)非??勺x的方式進(jìn)行記錄,這個(gè)特性非常適合做災(zāi)難性的誤刪除的緊急恢復(fù)。比如某人不小心用 flushall 命令清空了所有數(shù)據(jù),只要這個(gè)時(shí)候后臺(tái) rewrite 還沒(méi)有發(fā)生,那么就可以立即拷貝 AOF 文件,將最后一條 flushall 命令給刪了,然后再將該 AOF 文件放回去,就可以通過(guò)恢復(fù)機(jī)制,自動(dòng)恢復(fù)所有數(shù)據(jù)。
  • 對(duì)于同一份數(shù)據(jù)來(lái)說(shuō),AOF 日志文件通常比 RDB 數(shù)據(jù)快照文件更大。
  • AOF 開(kāi)啟后,支持的寫(xiě) QPS 會(huì)比 RDB 支持的寫(xiě) QPS 低,因?yàn)?AOF 一般會(huì)配置成每秒 fsync 一次日志文件,當(dāng)然,每秒一次 fsync,性能也還是很高的。(如果實(shí)時(shí)寫(xiě)入,那么 QPS 會(huì)大降,redis 性能會(huì)大大降低)
  • 以前 AOF 發(fā)生過(guò) bug,就是通過(guò) AOF 記錄的日志,進(jìn)行數(shù)據(jù)恢復(fù)的時(shí)候,沒(méi)有恢復(fù)一模一樣的數(shù)據(jù)出來(lái)。所以說(shuō),類(lèi)似 AOF 這種較為復(fù)雜的基于命令日志 / merge / 回放的方式,比基于 RDB 每次持久化一份完整的數(shù)據(jù)快照文件的方式,更加脆弱一些,容易有 bug。不過(guò) AOF 就是為了避免 rewrite 過(guò)程導(dǎo)致的 bug,因此每次 rewrite 并不是基于舊的指令日志進(jìn)行 merge 的,而是基于當(dāng)時(shí)內(nèi)存中的數(shù)據(jù)進(jìn)行指令的重新構(gòu)建,這樣健壯性會(huì)好很多。

RDB 和 AOF 到底該如何選擇

  • 不要僅僅使用 RDB,因?yàn)槟菢訒?huì)導(dǎo)致你丟失很多數(shù)據(jù);
  • 也不要僅僅使用 AOF,因?yàn)槟菢佑袃蓚€(gè)問(wèn)題:第一,你通過(guò) AOF 做冷備,沒(méi)有 RDB 做冷備來(lái)的恢復(fù)速度更快;第二,RDB 每次簡(jiǎn)單粗暴生成數(shù)據(jù)快照,更加健壯,可以避免 AOF 這種復(fù)雜的備份和恢復(fù)機(jī)制的 bug;
  • redis 支持同時(shí)開(kāi)啟開(kāi)啟兩種持久化方式,我們可以綜合使用 AOF 和 RDB 兩種持久化機(jī)制,用 AOF 來(lái)保證數(shù)據(jù)不丟失,作為數(shù)據(jù)恢復(fù)的第一選擇; 用 RDB 來(lái)做不同程度的冷備,在 AOF 文件都丟失或損壞不可用的時(shí)候,還可以使用 RDB 來(lái)進(jìn)行快速的數(shù)據(jù)恢復(fù)。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容