日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Redis系列(三):Redis的持久化機(jī)制(RDB、AOF)

 路人甲Java 2022-04-13

本篇博客是Redis系列的第3篇,主要講解下Redis的2種持久化機(jī)制:RDB和AOF。

本系列的前2篇可以點(diǎn)擊以下鏈接查看:

Redis系列(一):Redis簡(jiǎn)介及環(huán)境安裝

Redis系列(二):Redis的5種數(shù)據(jù)結(jié)構(gòu)及其常用命令

1. 為什么需要持久化?

因?yàn)镽edis是內(nèi)存數(shù)據(jù)庫(kù),它將自己的數(shù)據(jù)存儲(chǔ)在內(nèi)存里面,一旦Redis服務(wù)器進(jìn)程退出或者運(yùn)行Redis服務(wù)器的計(jì)算機(jī)停機(jī),Redis服務(wù)器中的數(shù)據(jù)就會(huì)丟失。

為了避免數(shù)據(jù)丟失,所以Redis提供了持久化機(jī)制,將存儲(chǔ)在內(nèi)存中的數(shù)據(jù)保存到磁盤(pán)中,用于在Redis服務(wù)器進(jìn)程退出或者運(yùn)行Redis服務(wù)器的計(jì)算機(jī)停機(jī)導(dǎo)致數(shù)據(jù)丟失時(shí),快速的恢復(fù)之前Redis存儲(chǔ)在內(nèi)存中的數(shù)據(jù)。

Redis提供了2種持久化方式,分別為:

  1. RDB持久化
  2. AOF持久化

接下來(lái),我們一一詳解。

2. RDB持久化

RDB持久化是將某個(gè)時(shí)間點(diǎn)上Redis中的數(shù)據(jù)保存到一個(gè)RDB文件中,如下所示:

基于RDB持久化的上述性質(zhì),所以RDB持久化也叫做快照持久化。

該文件是一個(gè)經(jīng)過(guò)壓縮的二進(jìn)制文件,通過(guò)該文件可以還原生成RDB文件時(shí)Redis中的數(shù)據(jù),如下所示:

2.1 創(chuàng)建RDB文件

Redis提供了2個(gè)命令來(lái)創(chuàng)建RDB文件,一個(gè)是SAVE,另一個(gè)是BGSAVE。

SAVE命令會(huì)阻塞Redis服務(wù)器進(jìn)程,直到RDB文件創(chuàng)建完畢為止,在服務(wù)器進(jìn)程阻塞期間,服務(wù)器不能處理任何命令請(qǐng)求,如下所示:

BGSAVE命令會(huì)派生出一個(gè)子進(jìn)程,然后由子進(jìn)程負(fù)責(zé)創(chuàng)建RDB文件,服務(wù)器進(jìn)程(父進(jìn)程)繼續(xù)處理命令請(qǐng)求,如下所示:

以上描述也是這2個(gè)命令的區(qū)別,這里是重點(diǎn),面試經(jīng)常會(huì)問(wèn)到。

因?yàn)锽GSAVE命令可以在不阻塞服務(wù)器進(jìn)程的情況下執(zhí)行,所以推薦使用BGSAVE命令。

我們可以手動(dòng)執(zhí)行該命令,如上面截圖所示,但還是推薦設(shè)置下Redis服務(wù)器配置文件的save選項(xiàng),讓服務(wù)器每隔一段時(shí)間自動(dòng)執(zhí)行一次BGSAVE命令。

我們可以通過(guò)save選項(xiàng)設(shè)置多個(gè)保存條件,只要其中任意一個(gè)條件被滿足,服務(wù)器就會(huì)執(zhí)行BGSAVE命令。

save選項(xiàng)設(shè)置的默認(rèn)條件如下所示:

save 900 1

save 300 10

save 60 10000

默認(rèn)的配置條件表示,只要滿足以下3個(gè)條件中的任意1個(gè),BGSAVE命令就會(huì)被執(zhí)行:

  • 服務(wù)器在900s(即15分鐘)之內(nèi),對(duì)數(shù)據(jù)庫(kù)進(jìn)行了至少1次修改
  • 服務(wù)器在300s(即5分鐘)之內(nèi),對(duì)數(shù)據(jù)庫(kù)進(jìn)行了至少10次修改
  • 服務(wù)器在60s(即1分鐘)之內(nèi),對(duì)數(shù)據(jù)庫(kù)進(jìn)行了至少10000次修改

當(dāng)滿足條件執(zhí)行BGSAVE命令時(shí),輸出日志如下圖所示:

生成的RDB文件會(huì)根據(jù)Redis配置文件中的名稱和路徑來(lái)保存,相關(guān)的2個(gè)配置如下所示:

最終生成的RDB文件如下所示(截圖為本機(jī)Windows環(huán)境,Linux環(huán)境下路徑會(huì)稍有不同):

2.2 載入RDB文件

首先,我們要明確的是,載入RDB文件的目的是為了在Redis服務(wù)器進(jìn)程重新啟動(dòng)之后還原之前存儲(chǔ)在Redis中的數(shù)據(jù)。

然后,Redis載入RDB文件并沒(méi)有專門(mén)的命令,而是在Redis服務(wù)器啟動(dòng)時(shí)自動(dòng)執(zhí)行的。

而且,Redis服務(wù)器啟動(dòng)時(shí)是否會(huì)載入RDB文件還取決于服務(wù)器是否啟用了AOF持久化功能,具體判斷邏輯為:

  1. 只有在AOF持久化功能處于關(guān)閉狀態(tài)時(shí),服務(wù)器才會(huì)使用RDB文件來(lái)還原數(shù)據(jù)。
  2. 如果服務(wù)器開(kāi)啟了AOF持久化功能,那么服務(wù)器會(huì)優(yōu)先使用AOF文件來(lái)還原數(shù)據(jù)。

以上判斷邏輯如下圖所示:

默認(rèn)情況下,Redis服務(wù)器的AOF持久化功能是關(guān)閉的,所以Redis服務(wù)器在啟動(dòng)時(shí)會(huì)載入RDB文件,

啟動(dòng)日志如下所示:

2.3 服務(wù)器狀態(tài)

創(chuàng)建和載入RDB文件,可能存在的服務(wù)器狀態(tài)有以下3種:

  1. 當(dāng)執(zhí)行SAVE命令時(shí),Redis服務(wù)器會(huì)被阻塞,此時(shí)客戶端發(fā)送的所有命令請(qǐng)求都會(huì)被阻塞,只有在服務(wù)器執(zhí)行完SAVE命令,重新開(kāi)始接受命令請(qǐng)求之后,客戶端發(fā)送的命令請(qǐng)求才會(huì)被處理。
  2. 當(dāng)執(zhí)行BGSAVE命令時(shí),Redis服務(wù)器不會(huì)被阻塞,Redis服務(wù)器仍然可以繼續(xù)處理客戶端發(fā)送的命令請(qǐng)求。
  3. 服務(wù)器在載入RDB文件期間,會(huì)一直處于阻塞狀態(tài),直到RDB文件載入成功。

3. AOF持久化

AOF持久化是通過(guò)保存Redis服務(wù)器所執(zhí)行的寫(xiě)命令來(lái)記錄數(shù)據(jù)庫(kù)數(shù)據(jù)的,如下圖所示:

默認(rèn)情況下,AOF持久化功能是關(guān)閉的,如果想要打開(kāi),可以修改下圖所示的配置:

舉個(gè)例子,假設(shè)Redis中還沒(méi)有存儲(chǔ)任何數(shù)據(jù),我們執(zhí)行了如下所示的命令:

然后我們會(huì)發(fā)現(xiàn)Redis服務(wù)器生成了1個(gè)名為appendonly.aof的文件,打開(kāi)該文件,我們可以看到上面執(zhí)行的3個(gè)寫(xiě)命令都存儲(chǔ)在該文件中:

3.1 AOF持久化的實(shí)現(xiàn)

當(dāng)AOF持久化功能處于打開(kāi)狀態(tài)時(shí),Redis服務(wù)器在執(zhí)行完一個(gè)寫(xiě)命令之后,會(huì)以協(xié)議格式(如上面截圖中AOF文件里保存寫(xiě)命令的格式)將被執(zhí)行的寫(xiě)命令追加到服務(wù)器狀態(tài)的AOF緩沖區(qū)的末尾,然后Redis服務(wù)器會(huì)根據(jù)配置文件中appendfsync選項(xiàng)的值來(lái)決定何時(shí)將AOF緩沖區(qū)中的內(nèi)容寫(xiě)入和同步到AOF文件里面。

appendfsync選項(xiàng)有以下3個(gè)值:

  1. always

    從安全性來(lái)說(shuō),always是最安全的(丟失數(shù)據(jù)最少),因?yàn)榧词钩霈F(xiàn)故障停機(jī),數(shù)據(jù)庫(kù)也只會(huì)丟失一個(gè)事件循環(huán)中所產(chǎn)生的命令數(shù)據(jù)。

    從效率來(lái)說(shuō),always的效率最慢,因?yàn)榉?wù)器在每個(gè)事件循環(huán)都要將AOF緩沖區(qū)中的所有內(nèi)容寫(xiě)入到AOF文件,并且同步AOF文件。

  2. everysec

    從安全性來(lái)說(shuō),everysec模式下,即使出現(xiàn)故障停機(jī),數(shù)據(jù)庫(kù)只會(huì)丟失一秒鐘的命令數(shù)據(jù)。

    從效率來(lái)說(shuō),everysec模式足夠快,因?yàn)榉?wù)器在每個(gè)事件循環(huán)都要將AOF緩沖區(qū)中的所有內(nèi)容寫(xiě)入到AOF文件,并且每隔一秒就要在子線程中對(duì)AOF文件進(jìn)行同步。

  3. no

    從安全性來(lái)說(shuō),no模式下,如果出現(xiàn)故障停機(jī),數(shù)據(jù)庫(kù)會(huì)丟失上次同步AOF文件之后的所有寫(xiě)命令數(shù)據(jù),具有不確定性,因?yàn)榉?wù)器在每個(gè)事件循環(huán)都要將AOF緩沖區(qū)中的所有內(nèi)容寫(xiě)入到AOF文件,至于何時(shí)對(duì)AOF文件進(jìn)行同步,則由操作系統(tǒng)控制。

    從效率來(lái)說(shuō),no模式和everysec模式的效率差不多。

appendfsync選項(xiàng)的默認(rèn)值是everysec,也推薦使用這個(gè)值,因?yàn)榧缺WC了效率又保證了安全性。

3.2 載入AOF文件

因?yàn)锳OF文件包含了重建數(shù)據(jù)庫(kù)所需的所有寫(xiě)命令,所以Redis服務(wù)器只要讀入并重新執(zhí)行一遍AOF文件里面保存的寫(xiě)命令,就可以還原Redis服務(wù)器關(guān)閉之前的數(shù)據(jù)。

Redis讀取AOF文件并還原數(shù)據(jù)庫(kù)的詳細(xì)步驟如下:

  1. 創(chuàng)建一個(gè)不帶網(wǎng)絡(luò)連接的偽客戶端

    因?yàn)镽edis的命令只能在客戶端上下文中執(zhí)行,而載入AOF文件時(shí)所使用的命令直接來(lái)源于AOF文件而不是網(wǎng)絡(luò)連接,所以服務(wù)器使用了一個(gè)沒(méi)有網(wǎng)絡(luò)連接的偽客戶端來(lái)執(zhí)行AOF文件保存的寫(xiě)命令。

    偽客戶端執(zhí)行命令的效果和帶網(wǎng)絡(luò)連接的客戶端執(zhí)行命令的效果完全一樣。

  2. 從AOF文件中分析并讀取出一條寫(xiě)命令。

  3. 使用偽客戶端執(zhí)行被讀取出的寫(xiě)命令。

  4. 一直執(zhí)行步驟2和步驟3,直到AOF文件中的所有寫(xiě)命令都被執(zhí)行完畢。

以上步驟如下圖所示:

如果Redis服務(wù)器開(kāi)啟了AOF持久化功能,那么Redis服務(wù)器在啟動(dòng)時(shí)會(huì)載入AOF文件,

啟動(dòng)日志如下所示:

3.3 AOF重寫(xiě)

因?yàn)锳OF持久化是通過(guò)保存被執(zhí)行的寫(xiě)命令來(lái)記錄數(shù)據(jù)庫(kù)數(shù)據(jù)的,所以隨著Redis服務(wù)器運(yùn)行時(shí)間的增加,AOF文件中的內(nèi)容會(huì)越來(lái)越多,文件的體積會(huì)越來(lái)越大,如果不做控制,會(huì)有以下2點(diǎn)壞處:

  1. 過(guò)多的占用服務(wù)器磁盤(pán)空間,可能會(huì)對(duì)Redis服務(wù)器甚至整個(gè)宿主計(jì)算機(jī)造成影響。
  2. AOF文件的體積越大,使用AOF文件來(lái)進(jìn)行數(shù)據(jù)庫(kù)還原所需的時(shí)間就越多。

舉個(gè)例子,在客戶端執(zhí)行如下命令:

為了記錄這個(gè)list鍵的狀態(tài),AOF文件就需要保存上面執(zhí)行的6條命令。

為了解決AO文件體積越來(lái)越大的問(wèn)題,Redis提供了AOF文件重寫(xiě)功能,即Redis服務(wù)器會(huì)創(chuàng)建一個(gè)新的AOF文件來(lái)替代現(xiàn)有的AOF文件,新舊兩個(gè)AOF文件所保存的數(shù)據(jù)庫(kù)數(shù)據(jù)相同,但新AOF文件不會(huì)包含任何浪費(fèi)空間的冗余命令,所以新AOF文件的體積通常會(huì)比舊AOF文件的體積要小很多。

3.3.1 AOF重寫(xiě)的實(shí)現(xiàn)原理

AOF文件重寫(xiě)并不需要對(duì)現(xiàn)有的AOF文件進(jìn)行任何讀取、分析或者寫(xiě)入操作,而是通過(guò)讀取服務(wù)器當(dāng)前的數(shù)據(jù)庫(kù)數(shù)據(jù)來(lái)實(shí)現(xiàn)的。

仍然以上面的list鍵為例,舊的AOF文件保存了6條命令來(lái)記錄list鍵的狀態(tài),但list鍵的結(jié)果是“C” "D" "E" "F" "G"這樣的數(shù)據(jù),所以AOF文件重寫(xiě)時(shí),可以用一條RPUSH list “C” "D" "E" "F" "G"命令來(lái)代替之前的六條命令,這樣就可以將保存list鍵所需的命令從六條減少為一條了。

按照上面的原理,如果Redis服務(wù)器存儲(chǔ)的鍵值對(duì)足夠多,AOF文件重寫(xiě)生成的新AOF文件就會(huì)減少很多很多的冗余命令,進(jìn)而大大減小了AOF文件的體積。

綜上所述,AOF文件重寫(xiě)功能的實(shí)現(xiàn)原理為:

首先從數(shù)據(jù)庫(kù)中讀取鍵現(xiàn)在的值,然后用一條命令去記錄鍵值對(duì),代替之前記錄這個(gè)鍵值對(duì)的多條命令。

3.3.2 AOF后臺(tái)重寫(xiě)

因?yàn)锳OF文件重寫(xiě)會(huì)進(jìn)行大量的文件寫(xiě)入操作,所以執(zhí)行這個(gè)操作的線程將被長(zhǎng)時(shí)間阻塞。

因?yàn)镽edis服務(wù)器使用單個(gè)線程來(lái)處理命令請(qǐng)求,所以如果由服務(wù)器進(jìn)程直接執(zhí)行這個(gè)操作,那么在重寫(xiě)AOF文件期間,服務(wù)器將無(wú)法處理客戶端發(fā)送過(guò)來(lái)的命令請(qǐng)求。

為了避免上述問(wèn)題,Redis將AOF文件重寫(xiě)功能放到子進(jìn)程里執(zhí)行,這樣做有以下2個(gè)好處:

  1. 子進(jìn)程進(jìn)行AOF文件重寫(xiě)期間,服務(wù)器進(jìn)程(父進(jìn)程)可以繼續(xù)處理命令請(qǐng)求。
  2. 子進(jìn)程帶有服務(wù)器進(jìn)程的數(shù)據(jù)副本,使用子進(jìn)程而不是線程,可以在避免使用鎖的情況下,保證數(shù)據(jù)的安全性。

AOF后臺(tái)重寫(xiě)的步驟如下所示:

  1. 服務(wù)器進(jìn)程創(chuàng)建子進(jìn)程,子進(jìn)程開(kāi)始AOF文件重寫(xiě)

  2. 從創(chuàng)建子進(jìn)程開(kāi)始,服務(wù)器進(jìn)程執(zhí)行的所有寫(xiě)命令不僅要寫(xiě)入AOF緩沖區(qū),還要寫(xiě)入AOF重寫(xiě)緩沖區(qū)

    寫(xiě)入AOF緩沖區(qū)的目的是為了同步到原有的AOF文件。

    寫(xiě)入AOF重寫(xiě)緩沖區(qū)的目的是因?yàn)樽舆M(jìn)程在進(jìn)行AOF文件重寫(xiě)期間,服務(wù)器進(jìn)程還在繼續(xù)處理命令請(qǐng)求,

    而新的命令可能會(huì)對(duì)現(xiàn)有的數(shù)據(jù)庫(kù)進(jìn)行修改,從而使得服務(wù)器當(dāng)前的數(shù)據(jù)庫(kù)數(shù)據(jù)和重寫(xiě)后的AOF文件所

    保存的數(shù)據(jù)庫(kù)數(shù)據(jù)不一致。

  3. 子進(jìn)程完成AOF重寫(xiě)工作,向父進(jìn)程發(fā)送一個(gè)信號(hào),父進(jìn)程在接收到該信號(hào)后,會(huì)執(zhí)行以下操作:

    1.將AOF重寫(xiě)緩沖區(qū)中的所有內(nèi)容寫(xiě)入到新AOF文件中,這樣就保證了新AOF文件所保存的數(shù)據(jù)庫(kù)數(shù)據(jù)和服務(wù)器當(dāng)前的數(shù)據(jù)庫(kù)數(shù)據(jù)是一致的。

    2.對(duì)新的AOF文件進(jìn)行改名,原子地覆蓋現(xiàn)有的AOF文件,完成新舊兩個(gè)AOF文件的替換。

Redis提供了BGREWRITEAOF命令來(lái)執(zhí)行以上步驟,如下圖所示:

執(zhí)行完成后,打開(kāi)appendonly.aof文件,發(fā)現(xiàn)保存list鍵的命令從六條變?yōu)榱艘粭l:

除了手動(dòng)執(zhí)行BGREWRITEAOF命令外,Redis還提供了2個(gè)配置項(xiàng)用來(lái)自動(dòng)執(zhí)行BGREWRITEAOF命令:

auto-aof-rewrite-percentage 100

auto-aof-rewrite-min-size 64mb

該配置表示,當(dāng)AOF文件的體積大于64MB,并且AOF文件的體積比上一次重寫(xiě)之后的體積大了至少一倍(100%),Redis將自動(dòng)執(zhí)行BGREWRITEAOF命令。

4. RDB持久化、AOF持久化的區(qū)別

通過(guò)上面的講解,我們會(huì)發(fā)現(xiàn)Redis提供的2種持久化方法是有區(qū)別的,可以總結(jié)為以下4點(diǎn):

  1. 實(shí)現(xiàn)方式
  2. 文件體積
  3. 安全性
  4. 優(yōu)先級(jí)

接下來(lái)一一講解。

4.1 實(shí)現(xiàn)方式

RDB持久化是通過(guò)將某個(gè)時(shí)間點(diǎn)Redis服務(wù)器存儲(chǔ)的數(shù)據(jù)保存到RDB文件中來(lái)實(shí)現(xiàn)持久化的。

AOF持久化是通過(guò)將Redis服務(wù)器執(zhí)行的所有寫(xiě)命令保存到AOF文件中來(lái)實(shí)現(xiàn)持久化的。

4.2 文件體積

由上述實(shí)現(xiàn)方式可知,RDB持久化記錄的是結(jié)果,AOF持久化記錄的是過(guò)程,所以AOF持久化生成的AOF文件會(huì)有體積越來(lái)越大的問(wèn)題,Redis提供了AOF重寫(xiě)功能來(lái)減小AOF文件體積。

4.3 安全性

AOF持久化的安全性要比RDB持久化的安全性高,即如果發(fā)生機(jī)器故障,AOF持久化要比RDB持久化丟失的數(shù)據(jù)要少。

因?yàn)镽DB持久化會(huì)丟失上次RDB持久化后寫(xiě)入的數(shù)據(jù),而AOF持久化最多丟失1s之內(nèi)寫(xiě)入的數(shù)據(jù)(使用默認(rèn)everysec配置的話)。

4.4 優(yōu)先級(jí)

由于上述的安全性問(wèn)題,如果Redis服務(wù)器開(kāi)啟了AOF持久化功能,Redis服務(wù)器在啟動(dòng)時(shí)會(huì)使用AOF文件來(lái)還原數(shù)據(jù),如果Redis服務(wù)器沒(méi)有開(kāi)啟AOF持久化功能,Redis服務(wù)器在啟動(dòng)時(shí)會(huì)使用RDB文件來(lái)還原數(shù)據(jù),所以AOF文件的優(yōu)先級(jí)比RDB文件的優(yōu)先級(jí)高。

5. 源碼及參考

Josiah L. Carlson 《Reids實(shí)戰(zhàn)》

黃健宏 《Redis設(shè)計(jì)與實(shí)現(xiàn)》

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多