您好,登錄后才能下訂單哦!
AOF持久化及AOF重寫的配置:
默認(rèn)AOF方式是關(guān)閉的,如下圖:
如果要開(kāi)啟的話,就是把no改寫成yes。如下圖:
默認(rèn)文件名稱appendonly.aof,你也可以修改文件名。默認(rèn)保存目錄同樣也是配置文件中dir配置項(xiàng)中的設(shè)置,它和RDB共用一個(gè)目錄。如下圖:
默認(rèn)同步策略是每秒,如下圖:
我們對(duì)數(shù)據(jù)庫(kù)做一些操作然后查看一下appendonly.aof文件內(nèi)容
它會(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重寫策略
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)記錄的,如下圖:
當(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è)壓縮列表為例
根據(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ō)明 |
always | 將aof_buf緩沖區(qū)中的所有內(nèi)容寫入并同步到AOF文件中,立即執(zhí)行write()和fsync()系統(tǒng)調(diào)用。對(duì)于數(shù)據(jù)的安全性最高,但是執(zhí)行最慢,如果出現(xiàn)故障只會(huì)丟失一個(gè)事件循環(huán)的內(nèi)容。 |
everysec | 將aof_buf緩沖區(qū)的所有內(nèi)容寫入到AOF文件,如果上次同步AOF的時(shí)間距離本次超過(guò)1秒,則執(zhí)行同步,每隔一秒執(zhí)行一次write()和fsync()系統(tǒng)調(diào)用。數(shù)據(jù)安全性居中,執(zhí)行快,僅會(huì)丟失1秒的數(shù)據(jù)。 |
no | 將aof_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ū)中。
內(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、fsync和fdatasync三個(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)容,你就知道APPENDFSYNC中no參數(shù)的含義.
免責(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)容。