11.AOF持久化

RDB持久化通過(guò)保存數(shù)據(jù)庫(kù)中的鍵值對(duì)來(lái)記錄數(shù)據(jù)庫(kù)狀態(tài)

AOF持久化是通過(guò)保存Redis服務(wù)器所執(zhí)行的寫命令來(lái)記錄數(shù)據(jù)庫(kù)狀態(tài)。


AOF持久化

被寫入AOF文件的所有命令都是以Redis的命令請(qǐng)求協(xié)議格式保存的,因?yàn)镽edis的命令請(qǐng)求協(xié)議是純文本格式,所以可以直接打開(kāi)一個(gè)AOF文件,觀察里面的內(nèi)容。

服務(wù)器在啟動(dòng)時(shí),可以通過(guò)載入和執(zhí)行AOF文件中保存的命令來(lái)還原服務(wù)器關(guān)閉之前的狀態(tài)。

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

AOF的持久化功能的實(shí)現(xiàn)可以分為命令追加、文件寫入、文件同步三個(gè)部分。

11.1.1 命令追加

當(dāng)服務(wù)器打開(kāi)AOF持久化功能時(shí),服務(wù)器在執(zhí)行完一個(gè)寫命令之后,會(huì)以協(xié)議格式將被執(zhí)行的寫命令追加到服務(wù)器狀態(tài)的aof_buf緩沖區(qū)的末尾

11.1.2 AOF文件的寫入和同步

Redis服務(wù)器進(jìn)程就是一個(gè)事件循環(huán),這個(gè)循環(huán)中的文件事件負(fù)責(zé)接受客戶端的命令請(qǐng)求,以及向客戶端發(fā)送命令回復(fù),而時(shí)間事件則負(fù)責(zé)執(zhí)行像serverCron函數(shù)這樣需要定時(shí)運(yùn)行的函數(shù)。

服務(wù)器在每次結(jié)束一個(gè)事件循環(huán)之前,都會(huì)調(diào)用flushAppendOnlyFile函數(shù),考慮是否需要將aof_buf緩沖區(qū)中的內(nèi)容寫入和保存到AOF文件里面。

文件的寫入和同步

為了提高文件的寫入效率,現(xiàn)代操作系統(tǒng)中,當(dāng)用戶調(diào)用write函數(shù),將一些數(shù)據(jù)寫入文件時(shí),操作系統(tǒng)通常會(huì)將數(shù)據(jù)先暫時(shí)保存在一個(gè)內(nèi)存緩沖區(qū)里面,等到緩沖區(qū)被填滿時(shí)或者超過(guò)了指定的時(shí)限之后,才真正地將緩沖區(qū)中的數(shù)據(jù)寫入磁盤中。

這種做法雖然提高了效率,但是也為寫入數(shù)據(jù)帶來(lái)了安全問(wèn)題,為此系統(tǒng)提供了fsync和fdatasync兩個(gè)同步函數(shù),他們可以強(qiáng)制讓操作系統(tǒng)立即將緩沖區(qū)中的數(shù)據(jù)寫入到硬盤里面,從而確保寫入數(shù)據(jù)的安全性。

AOF持久化的效率和安全性

服務(wù)器配置appendfsync選項(xiàng)的值直接決定AOF持久化的效率和安全性。

appendfsync的值可以為no、everysec和always

當(dāng)appendfsync的值為always時(shí),服務(wù)器在每個(gè)事件循環(huán)都要將aof_buf緩沖區(qū)中的所有內(nèi)容寫入到AOF文件,并且同步AOF文件,所以always到效率是appendfsync三個(gè)值中最慢的,但是安全性是三個(gè)值中最高的,及時(shí)出現(xiàn)故障停機(jī),AOF持久化也只會(huì)丟失一個(gè)事件循環(huán)中所產(chǎn)生的命令數(shù)據(jù)。

當(dāng)appendfsync的值為everysec時(shí),服務(wù)器在每個(gè)事件循環(huán)都要把a(bǔ)of_buf緩沖區(qū)的所有內(nèi)容寫入到AOF文件中,每隔1s就要在子進(jìn)程中對(duì)AOF文件進(jìn)行一次同步。從效率上講,everysec模式足夠快,并且就算出現(xiàn)故障停機(jī),數(shù)據(jù)庫(kù)也只丟失1s的命令數(shù)據(jù)。

當(dāng)appendfsync的值為no時(shí),服務(wù)器在每個(gè)事件循環(huán)都要把a(bǔ)of_buf緩沖區(qū)的所有內(nèi)容寫入到AOF文件中,至于何時(shí)對(duì)AOF文件執(zhí)行同步,由操作系統(tǒng)控制。因?yàn)樘幱趎o模式下的flushappendOnlyFile調(diào)用無(wú)需執(zhí)行同步操作,所以該模式下的AOF文件寫入速度是最快的,因?yàn)檫@種模式會(huì)在系統(tǒng)緩存中累積一段時(shí)間的寫入數(shù)據(jù),所以這個(gè)模式的單次同步時(shí)間是3種模式中最長(zhǎng)的。從平攤操作的角度來(lái)看,no模式和everysec模式的效率類型,當(dāng)出現(xiàn)故障停機(jī)時(shí),使用no模式的服務(wù)器將丟失上次同步AOF文件之后的所有寫命令數(shù)據(jù)。

11.2 AOF文件的載入和還原

AOF文件中保存了重建數(shù)據(jù)庫(kù)狀態(tài)的所有寫命令,所以服務(wù)器只需讀入并重新執(zhí)行一遍AOF文件里保存的寫命令,就可以還原服務(wù)器關(guān)閉之前的數(shù)據(jù)庫(kù)狀態(tài)。

還原數(shù)據(jù)庫(kù)的詳細(xì)步驟:

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

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

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

4.一直執(zhí)行2.3,直到AOF中的所有寫命令都被處理完畢為止。

11.3 AOF重寫

因?yàn)锳OF持久化是通過(guò)保存被執(zhí)行的寫命令來(lái)記錄數(shù)據(jù)庫(kù)的狀態(tài)的,所以隨著服務(wù)器運(yùn)行時(shí)間的流逝,AOF文件中的內(nèi)容會(huì)越來(lái)越多,文件的體積也會(huì)越來(lái)越大,如果不加以控制的話,體積過(guò)大的AOF文件很可能對(duì)Redis服務(wù)器、甚至整個(gè)宿主計(jì)算機(jī)造成影響,并且AOF文件的體積越大,使用AOF文件進(jìn)行數(shù)據(jù)還原所需的時(shí)間就越多。

11.3.1 AOF文件重寫的實(shí)現(xiàn)

Redis將新生成的AOF文件替換舊的AOF文件的功能命名為“AOF文件重寫”,這個(gè)功能是通過(guò)讀取服務(wù)區(qū)當(dāng)前的數(shù)據(jù)庫(kù)狀態(tài)來(lái)實(shí)現(xiàn)的。

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

注意:為了避免在執(zhí)行命令時(shí)造成客戶端輸入緩沖區(qū)溢出,重寫程序在處理列表、哈希表、集合、有序集合這四種可能會(huì)帶有多個(gè)元素的鍵時(shí),會(huì)先檢查鍵所包含的元素?cái)?shù)量,如果元素?cái)?shù)量超過(guò)了redis.h/REDIS_AOF_REWRITE_ITEMS_PER_CMD常量的值,那么重寫程序?qū)⑹褂枚鄺l命令來(lái)記錄鍵的值,目前版本REDIS_AOF_REWIRTE_ITEMS_PER_CMD常量的值為64.

11.3.2 AOF后臺(tái)重寫

aof_rewrite函數(shù)可以很好地完成創(chuàng)建一個(gè)新AOF文件的任務(wù) ,但是,因?yàn)檫@個(gè)函數(shù)會(huì)進(jìn)行大量的寫入操作,所以調(diào)用這個(gè)函數(shù)的線程將被長(zhǎng)時(shí)間阻塞,因?yàn)镽edis是單進(jìn)程單線程來(lái)處理命令請(qǐng)求,所以如果由服務(wù)器直接調(diào)用aof_write函數(shù)的話,在重寫AOF文件期間,服務(wù)器將無(wú)法處理客戶端發(fā)來(lái)的命令請(qǐng)求。

Redis決定將AOF重寫放入子進(jìn)程中執(zhí)行,這樣做可以同時(shí)達(dá)到兩個(gè)目的:

1.子進(jìn)程進(jìn)行AOF重寫期間,服務(wù)器進(jìn)程(父進(jìn)程)可以繼續(xù)處理命令請(qǐng)求

2.子進(jìn)程帶有服務(wù)器進(jìn)程的數(shù)據(jù)副本,使用子進(jìn)程而不是線程,就是為了在避免使用鎖的情況下,保證數(shù)據(jù)的安全性。

一個(gè)問(wèn)題需要解決:因?yàn)樽舆M(jìn)程在進(jìn)行AOF重寫期間,服務(wù)器進(jìn)程還需要繼續(xù)處理命令請(qǐng)求,而新的命令可能會(huì)對(duì)現(xiàn)有的數(shù)據(jù)庫(kù)狀態(tài)進(jìn)行修改,從而使得服務(wù)器當(dāng)前的數(shù)據(jù)庫(kù)狀態(tài)和重寫后的AOF文件所保存的數(shù)據(jù)庫(kù)狀態(tài)不一致。

解決方法:redis服務(wù)器設(shè)置了一個(gè)AOF重寫緩沖區(qū),這個(gè)緩沖區(qū)在服務(wù)器創(chuàng)建子進(jìn)程之后開(kāi)始使用,當(dāng)Redis服務(wù)器執(zhí)行完一個(gè)寫命令之后,它會(huì)同時(shí)將這個(gè)寫命令發(fā)送給AOF緩沖區(qū)和AOF重寫緩沖區(qū)。

在子進(jìn)程執(zhí)行AOF重寫期間,服務(wù)器需要進(jìn)行以下操作:

1.執(zhí)行客戶端發(fā)來(lái)的命令。

2.將執(zhí)行后的寫命令追加到AOF緩沖區(qū)。

3.將執(zhí)行后的寫命令追加到AOF重寫緩沖區(qū)。

可以保證:

AOF緩沖區(qū)的內(nèi)容會(huì)定期被寫入和同步到AOF文件中,對(duì)現(xiàn)有AOF文件的處理會(huì)如常進(jìn)行。

從創(chuàng)建子進(jìn)程開(kāi)始,服務(wù)器執(zhí)行的所有寫命令都會(huì)被記錄到AOF重寫緩沖區(qū)里面。

當(dāng)子進(jìn)程完成AOF重寫工作之后,它會(huì)向父進(jìn)程發(fā)送一個(gè)信號(hào),父進(jìn)程在接到該信號(hào)之后,會(huì)調(diào)用一個(gè)信號(hào)處理函數(shù),并執(zhí)行以下操作:

1)將AOF重寫緩沖區(qū)的所有內(nèi)容寫入到新的AOF文件中,這時(shí),新的AOF文件保存的內(nèi)容和當(dāng)前數(shù)據(jù)庫(kù)狀態(tài)一致。

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

整個(gè)AOF后臺(tái)重寫過(guò)程中,只有信號(hào)處理函數(shù)執(zhí)行會(huì)對(duì)服務(wù)器進(jìn)程造成阻塞,其他時(shí)候AOF后臺(tái)重寫都不會(huì)對(duì)阻塞父進(jìn)程,這將AOF重寫對(duì)服務(wù)器性能造成的影響降到了最低。

?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 前言 在上一篇文章中,介紹了Redis內(nèi)存模型,從這篇文章開(kāi)始,將依次介紹Redis高可用相關(guān)的知識(shí)——持久化、復(fù)...
    Java架構(gòu)閱讀 2,503評(píng)論 3 21
  • 企業(yè)級(jí)redis集群架構(gòu)的特點(diǎn) 海量數(shù)據(jù) 高并發(fā) 高可用 要達(dá)到高可用,持久化是不可減少的,持久化主要是做災(zāi)難恢復(fù)...
    lucode閱讀 2,283評(píng)論 0 7
  • 文章已經(jīng)放到github上 ,如果對(duì)您有幫助 請(qǐng)給個(gè)star[https://github.com/qqxuanl...
    尼爾君閱讀 2,346評(píng)論 0 22
  • 一個(gè)企業(yè)的經(jīng)營(yíng)境界可以分為三層: 第一層,企業(yè)只制造滿足市場(chǎng)需求的產(chǎn)品,只是復(fù)制生產(chǎn),典型的從1到n的過(guò)程。 第二...
    亂紅N閱讀 998評(píng)論 0 4
  • 【日精進(jìn)打卡第131天】 【知~學(xué)習(xí)】 《六項(xiàng)精進(jìn)》2遍 共207遍 《大學(xué)》2遍 共218遍 【經(jīng)典名句分享】 ...
    小火紙兒閱讀 110評(píng)論 0 0

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