溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Redis(四):持久化之---AOF持久化的配置和原理

發(fā)布時(shí)間:2020-08-07 16:25:10 來(lái)源:網(wǎng)絡(luò) 閱讀:664 作者:linuxjavachen 欄目:數(shù)據(jù)庫(kù)

AOF持久化及AOF重寫的配置:


默認(rèn)AOF方式是關(guān)閉的,如下圖:

Redis(四):持久化之---AOF持久化的配置和原理

如果要開(kāi)啟的話,就是把no改寫成yes。如下圖:

Redis(四):持久化之---AOF持久化的配置和原理

默認(rèn)文件名稱appendonly.aof,你也可以修改文件名。默認(rèn)保存目錄同樣也是配置文件中dir配置項(xiàng)中的設(shè)置,它和RDB共用一個(gè)目錄。如下圖:

Redis(四):持久化之---AOF持久化的配置和原理

默認(rèn)同步策略是每秒,如下圖:

Redis(四):持久化之---AOF持久化的配置和原理

我們對(duì)數(shù)據(jù)庫(kù)做一些操作然后查看一下appendonly.aof文件內(nèi)容

Redis(四):持久化之---AOF持久化的配置和原理

它會(huì)記錄所有寫操作內(nèi)容。

*2表示2個(gè)參數(shù)
$6表示第一個(gè)參數(shù)長(zhǎng)度為6
SELECT第一個(gè)參數(shù)
$1第二個(gè)參數(shù)長(zhǎng)度為1
0第二個(gè)參數(shù)

AOF重寫策略

Redis(四):持久化之---AOF持久化的配置和原理


AOF持久化實(shí)現(xiàn)原理:


當(dāng)AOF持久化開(kāi)啟后,當(dāng)對(duì)數(shù)據(jù)庫(kù)進(jìn)行一次更新操作后,更新命令就會(huì)被追加到aof_buf緩沖區(qū)的末尾,然后由緩沖區(qū)寫入到AOF文件。

AOF文件中記錄的內(nèi)容就是對(duì)數(shù)據(jù)更新操作的指令。這個(gè)文件本身就是以文本來(lái)記錄的,如下圖

Redis(四):持久化之---AOF持久化的配置和原理

當(dāng)需要恢復(fù)數(shù)據(jù)的時(shí)候,通過(guò)執(zhí)行AOF文件中記錄的更新指令,就可以完成。人為的看里面的指令,然后手動(dòng)敲命令也可以完成。


AOF重寫實(shí)現(xiàn)原理:


因?yàn)?/span>AOF持久化是通過(guò)記錄命令的方式來(lái)保存數(shù)據(jù)庫(kù)狀態(tài)的,隨著時(shí)間的推移AOF文件肯定會(huì)逐漸增大,如果不加以控制會(huì)對(duì)AOF持久化性能以及數(shù)據(jù)恢復(fù)造成影響。下面舉例來(lái)更加形象的說(shuō)明重寫的必要:

我們以一個(gè)壓縮列表為例

Redis(四):持久化之---AOF持久化的配置和原理

根據(jù)AOF的原理,那么上面紅色方框中的5條命令都要追加到AOF文件中,其實(shí)我們看到最后list的狀態(tài)就是BCDEF值。也就是說(shuō)為例實(shí)現(xiàn)最后的狀態(tài),需要追加5條命令。所以在大量?jī)?nèi)存讀寫的業(yè)務(wù)里AOF文件增長(zhǎng)的很快,為例解決這個(gè)問(wèn)題,Redis提供了AOF重寫功能。

AOF重寫就是創(chuàng)建一個(gè)新的AOF文件來(lái)替換現(xiàn)有的AOF文件,實(shí)際上AOF重寫并不對(duì)現(xiàn)有的舊AOF文件進(jìn)行操作。

以上面例子來(lái)說(shuō),當(dāng)進(jìn)行重寫的時(shí)候直接從數(shù)據(jù)庫(kù)里去獲取list的最新?tīng)顟B(tài),然后在新的AOF文件中直接寫一條rpushlist B C D E F命令,從而避免寫5條的操作,這樣AOF文件的增長(zhǎng)速度就會(huì)降低,同時(shí)容量也不會(huì)特別大。

AOF重寫程序aof_rewrite函數(shù)去完成創(chuàng)建新的AOF文件的任務(wù),但是該函數(shù)并不會(huì)由Redis主進(jìn)程去直接調(diào)用,而是使用子進(jìn)程后臺(tái)去執(zhí)行(BGREWRITEAOF,該命令其實(shí)就是執(zhí)行aof_rewrite,只不過(guò)是由子進(jìn)程去調(diào)用的),這時(shí)主進(jìn)程就會(huì)不被阻塞,那么就可以在執(zhí)行重寫的過(guò)程中父進(jìn)程可以繼續(xù)對(duì)外提供響應(yīng)。整個(gè)過(guò)程如下:

  • 當(dāng)重寫被觸發(fā)時(shí)父進(jìn)程調(diào)用一個(gè)函數(shù),該函數(shù)創(chuàng)建一個(gè)子進(jìn)程用于執(zhí)行BGREWRITEAOF,該子進(jìn)程創(chuàng)建一個(gè)臨時(shí)文件,然后父進(jìn)程繼續(xù)對(duì)外提供讀寫服務(wù)

  • 子進(jìn)程遍歷數(shù)據(jù)庫(kù),將每個(gè)鍵值的最新?tīng)顟B(tài)輸出到臨時(shí)文件中,在BGREWRITEAOF過(guò)程中,父進(jìn)程把所有對(duì)數(shù)據(jù)庫(kù)的更新命令同時(shí)寫入到AOF緩沖區(qū)和AOF重寫緩沖區(qū)(aof_rewrite_buf_blocks),AOF緩沖區(qū)(aof_buf)會(huì)繼續(xù)同步到現(xiàn)有AOF文件中(一般情況下在AOF重寫期間不建議把AOF緩沖區(qū)的內(nèi)容同步到現(xiàn)有的AOF文件中,這會(huì)降低性能,默認(rèn)為NO

  • AOF重寫完成后子進(jìn)程通知父進(jìn)程,父進(jìn)程調(diào)用信號(hào)處理函數(shù)

  • 信號(hào)處理函數(shù)會(huì)阻塞父進(jìn)程對(duì)外提供讀寫操作(時(shí)間很短,不阻塞就又會(huì)出現(xiàn)數(shù)據(jù)不一致的情況),然后將AOF重寫緩沖區(qū)的內(nèi)容寫入到新的AOF文件中,最后用新的AOF文件替換現(xiàn)有AOF文件(更名操作)


APPENDFSYNC選項(xiàng)說(shuō)明:


參數(shù)說(shuō)明
alwaysaof_buf緩沖區(qū)中的所有內(nèi)容寫入同步AOF文件中,立即執(zhí)行write()fsync()系統(tǒng)調(diào)用。對(duì)于數(shù)據(jù)的安全性最高,但是執(zhí)行最慢,如果出現(xiàn)故障只會(huì)丟失一個(gè)事件循環(huán)的內(nèi)容。
everysecaof_buf緩沖區(qū)的所有內(nèi)容寫入AOF文件,如果上次同步AOF的時(shí)間距離本次超過(guò)1秒,則執(zhí)行同步,每隔一秒執(zhí)行一次write()fsync()系統(tǒng)調(diào)用。數(shù)據(jù)安全性居中,執(zhí)行快,僅會(huì)丟失1秒的數(shù)據(jù)。
noaof_buf緩沖區(qū)的所有內(nèi)容寫入AOF文件,但是何時(shí)同步由操作系統(tǒng)決定,僅執(zhí)行write()系統(tǒng)調(diào)用。寫入動(dòng)作效率高,但是不執(zhí)行同步,但是單次同步消耗時(shí)間最長(zhǎng),數(shù)據(jù)安全性最低,會(huì)丟失上一次同步之后的所有數(shù)據(jù)。

這里要特別說(shuō)明一下Linux系統(tǒng)的文件寫入和同步原理,為什么要說(shuō)這個(gè),因?yàn)椴唤忉屢幌逻@個(gè)過(guò)程,你就很難理解APPENDFSYNC選項(xiàng)中的no參數(shù),如果把Always理解為總是、一直或者實(shí)時(shí);而把everysec理解為每秒的話,那no的含義難道是不執(zhí)行AOF文件同步嗎?如果不同步文件,那開(kāi)啟AOF持久化干嘛呢?

Redis調(diào)用appendfsync函數(shù)的時(shí)候,其實(shí)是先調(diào)用一個(gè)write()函數(shù),然后再調(diào)用sync()或者fsync()函數(shù)(對(duì)于任何程序來(lái)說(shuō)只要想把數(shù)據(jù)寫入磁盤其過(guò)程都一樣,有些也有例外)。

用戶空間:常規(guī)進(jìn)程所在區(qū)域,用戶發(fā)起的,此區(qū)域的代碼不能直接訪問(wèn)硬件

內(nèi)核空間:操作系統(tǒng)所在區(qū)域,能和設(shè)備控制器通訊

當(dāng)調(diào)用了write()函數(shù)時(shí),該函數(shù)一旦返回正常值,我們可能就認(rèn)為數(shù)據(jù)已經(jīng)寫入到了磁盤,但實(shí)際上,操作系統(tǒng)在實(shí)現(xiàn)磁盤文件的IO時(shí),為了保證IO的效率,會(huì)在內(nèi)存中使用一段專門的地址空間,該空間叫做內(nèi)核空間,而內(nèi)核空間之內(nèi)又會(huì)有一段是用作IO的數(shù)據(jù)緩沖區(qū)(這個(gè)緩沖區(qū)和之前說(shuō)的aof_buf緩沖區(qū)不是一個(gè)概念,雖然都在內(nèi)存中),write()函數(shù)的作用就是把數(shù)據(jù)寫入到內(nèi)核空間的IO緩沖區(qū)中。

Redis(四):持久化之---AOF持久化的配置和原理

內(nèi)核空間的IO緩沖區(qū)也有一定大小,當(dāng)該緩沖區(qū)沒(méi)有寫滿時(shí)或者沒(méi)有到一個(gè)同步周期時(shí),會(huì)持續(xù)的把write()函數(shù)傳遞的數(shù)據(jù)寫入到該緩沖區(qū)中,而當(dāng)該緩沖區(qū)寫滿或者到了一個(gè)同步周期,則會(huì)把該緩沖區(qū)的內(nèi)容提交到輸出隊(duì)列,當(dāng)需要數(shù)據(jù)到達(dá)隊(duì)列隊(duì)首的時(shí)候,開(kāi)始執(zhí)行真正的磁盤IO操作,把數(shù)據(jù)寫入磁盤(這里雖然用來(lái)寫入磁盤,但是真正的動(dòng)作不是移動(dòng)而是復(fù)制,復(fù)制完成之后,內(nèi)核空間的IO緩沖區(qū)才會(huì)釋放該數(shù)據(jù)占用的空間)。這種方式叫做延遲寫入。

所以這就會(huì)出現(xiàn)一個(gè)問(wèn)題,當(dāng)調(diào)用了write()函數(shù)后并不等于數(shù)據(jù)真的保存到了磁盤,但是這里又會(huì)有一個(gè)錯(cuò)覺(jué),就是你再次請(qǐng)求該文件的時(shí)候,可以顯示你最后一次更新的內(nèi)容,其實(shí)這個(gè)內(nèi)容并不是從磁盤上讀取過(guò)來(lái)的,而是從用戶空間的緩沖區(qū)讀取的。接著剛才提到的問(wèn)題,如果數(shù)據(jù)在內(nèi)核空間的IO緩沖區(qū)內(nèi),而此時(shí)操作系統(tǒng)出現(xiàn)故障、斷電等異常情況就會(huì)造成數(shù)據(jù)丟失。

為了解決數(shù)據(jù)丟失問(wèn)題,Unix系統(tǒng)提供了sync、fsyncfdatasync三個(gè)函數(shù)。

函數(shù)功能
sync函數(shù)返回0表示成功,該函數(shù)負(fù)責(zé)把所有內(nèi)核空間中IO緩沖區(qū)內(nèi)修改過(guò)的內(nèi)容推送到輸入隊(duì)列,然后就返回,它并不等待所有磁盤IO操作完成。所以即使調(diào)用了sync函數(shù),也不等于成功保存到磁盤了。
fsync函數(shù)返回0表示成功,與sync不同,它只會(huì)對(duì)指定文件描述符的單一文件生效,強(qiáng)制與該文件相連的所有修改過(guò)的數(shù)據(jù)傳送到磁盤上,并且等待磁盤IO完畢,然后返回。當(dāng)該函數(shù)返回0時(shí),才真正表示成功保存到磁盤。數(shù)據(jù)庫(kù)會(huì)在調(diào)用了write()之后調(diào)用fsync()。
fdatasync它與fsync類似,它只影響文件數(shù)據(jù)部分,不涉及數(shù)據(jù)屬性,比如inode信息。所以相對(duì)于fsync它需要較少的寫磁盤操作。

所以看了上面的內(nèi)容,你就知道APPENDFSYNCno參數(shù)的含義.

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI