redis之AOF和RDB持久化
寫在前面
redis數(shù)據(jù)存儲在內(nèi)存,為了避免服務器重啟或者是宕機導致數(shù)據(jù)全部丟失,提供了數(shù)據(jù)持久化機制,有AOF(Append Only File)和RDB,接下來我們分別看下。
1:AOF
如下是我本地環(huán)境生成aof文件:
1.1:AOF日志的實現(xiàn)
首先我們需要配置appendonly yes來打開AOF持久化,之后當我們執(zhí)行完數(shù)據(jù)修改命令后,redis就會將命令記錄到aof文件中,這個過程不同于MySQL的WAL 機制(MySQL要解決主要問題數(shù)據(jù)的安全存儲,而redis要解決的主要問題是高性能的數(shù)據(jù)存取),在寫數(shù)據(jù)之前先寫日志,redis是寫數(shù)據(jù)之后再寫日志,這樣做的其中一個原因是可以不用對命令本身的語法進行校驗了(既然都執(zhí)行成功了,肯定語法沒有問題),該過程如下圖:
如執(zhí)行命令set aa bbbb則生成的aof日志如下:
*3 $3 set $2 aa $4 bbbb含義如下:
*3:命令由3部分組成 $數(shù)字:代表接下來是命令的一部分,數(shù)字代表該部分的長度通過以上信息可以反推出命令set aa bbbb,就可以用來備份和恢復數(shù)據(jù)了。另外針對aof的寫回策略提供了若干個參數(shù)來控制,接下來繼續(xù)看下。
1.2:寫回策略
目前redis的寫回策略有三種,通過配置項appendfsync設置,如下:
Always:同步寫回,使用主線程,所以會影響到主線程的性能。 Everysec:每秒寫回,先將命令寫到aof的緩沖區(qū),然后其他線程每隔一秒寫到aof文件。 No:操作系統(tǒng)控制寫回,命令僅僅寫道aof緩沖區(qū),由操作系統(tǒng)控制寫到aof文件。對比如下表:
隨著越來越多的命令寫入到aof文件,aof文件會變得越來越大,而aof文件的不斷增大可能會產(chǎn)生如下的問題:
1:達到了操作系統(tǒng)對單文件大小的限制,從而無法繼續(xù)寫入 2:文件增大之后數(shù)據(jù)寫入的速度會變慢,影響寫入性能 3:文件過大,數(shù)據(jù)恢復的速度慢為了解決以上可能的問題,redis提供了AOF重寫機制。
1.3:AOF重寫機制
aof重寫機制的原理是多合一,即將多個命令合并成一個命令,因為可能會對一個key重復操作多次,所以同一個key的操作命令會被記錄多次,但是對于恢復數(shù)據(jù)而言,只需要最終的一個數(shù)據(jù)狀態(tài)就行了,所以根據(jù)數(shù)據(jù)當前的狀態(tài)反向生成一條命令即可,這就是多合一的過程,如下圖對一個list的多次操作執(zhí)行重寫的過程:
為了完成AOF重寫過程,redis會fork處一個新的子進程bgrewriteaof,并將當前內(nèi)存中的數(shù)據(jù)拷貝一份,然后使用當前最新的數(shù)據(jù)生成對應的命令,并寫到一個新的aof文件中,這個過程就是AOF重寫,可以參考下圖:
aof重寫完成后,就可以使用新的aof文件替換舊的aof文件了。
2:RDB
如下是我本地生成rdb文件:
前面我們分析了AOF持久化,但這種方式有一個問題,就是當修改命令變多時會導致文件過大,從而導致數(shù)據(jù)恢復速度慢。這個問題我們可以通過RDB(redis database)來解決。
2.1:原理和配置
- 原理
Redis通過定時任務掃描數(shù)據(jù)的變化是否滿足某個規(guī)則,如果是滿足了規(guī)則則使用操作系統(tǒng)提供的相關(guān)機制,則調(diào)用fork()創(chuàng)建子進程,對redis當前的內(nèi)存空間生成dump.rdb快照文件,該文件存儲了內(nèi)存數(shù)據(jù)對應的二進制數(shù)據(jù),可以直接加載到內(nèi)存中來恢復redis的數(shù)據(jù),恢復速度快。 - 配置策略
redis有兩種配置策略,一種是手動觸發(fā)策略,另外一種是自動觸發(fā)策略,其中自動觸發(fā)策略可以通過save,bgsave命令來手動觸發(fā),前者會使用主線程執(zhí)行備份,如下:
注意:LASTSAVE 命令用于查看 BGSAVE 命令是否執(zhí)行成功。
自動觸發(fā)策略通過如下配置:
save 900 1 save 300 10 save 60 10000以上配置的格式是save 時長 修改次數(shù),以上配置的含義是如果是在900內(nèi)發(fā)生至少一次更新,或者在300內(nèi)發(fā)生至少10次更新,或者是60秒內(nèi)發(fā)生至少10000次更新,則執(zhí)行bgsave生成rdb快照文件,并且生成文件后用于觸發(fā)策略的計數(shù)和計時都會重置。
2.2:復制都有哪些問題
在進行復制的時候,還允許數(shù)據(jù)更新嗎?如果是允許更新的話,就會有數(shù)據(jù)一致性的問題,如果是不允許更新的話,則會影響正常的數(shù)據(jù)更新。當然,影響正常的數(shù)據(jù)更新肯定是不允許的,因為會嚴重影響業(yè)務,甚至可能會出現(xiàn)線上事故,而數(shù)據(jù)一致性的問題更加不允許了,如果是后續(xù)使用其恢復數(shù)據(jù)的話,問題就更大了,所以只需要解決允許更新時有數(shù)據(jù)一致性的問題就可以了,redis的做法是使用COW(將要更新的數(shù)據(jù)copy出一份,直接更新copy的那份)機制,即更新時將更新目標對應的內(nèi)存頁復制出來一份,對復制的內(nèi)存頁執(zhí)行更新,則原始數(shù)據(jù)不會受到影響,待rdb生成完畢后,再將COW的內(nèi)存頁重新寫回到原始內(nèi)存頁就行了(這個過程很快),這樣就能解決數(shù)據(jù)一致性的問題了,參考下圖:
好了,現(xiàn)在我們已經(jīng)能夠在不影響客戶端更新的情況下獲取符合數(shù)據(jù)一致性要求的快照了,但是更新時時刻都在發(fā)生的,那么在這次快照生成之后多久之后再次生成呢,如果是頻率過慢,比如十分鐘一次,如果發(fā)生宕機,則上次快照到宕機時刻的所有數(shù)據(jù)都會丟失,如果是過快,比如一秒一次,這樣可以大大減少宕機造成的數(shù)據(jù)丟失,但是會對系統(tǒng)的IO等資源造成比較大的壓力,而且創(chuàng)建子進程的fork操作也是會阻塞主線程,因此也會影響到正常的數(shù)據(jù)操作,其實我們只需要處理好兩次快照之間的數(shù)據(jù)就行了,一種方案是記錄修改日志,即記錄對數(shù)據(jù)都做了什么修改,如下圖:
這種方案也沒有太大問題,但是在redis4.0中提供了更好的一種方案,即通過rdb和aof混用的方式,就巧妙的將這個問題解決了,即兩次快照空隙的數(shù)據(jù)修改通過aof日志方式記錄,則就既能使用到rdb恢復速度快的優(yōu)勢,也能夠規(guī)避aof文件過大帶來的問題,發(fā)揮其記錄簡單的優(yōu)勢,此時,rdb就是全量備份,而aof就是增量備份,二者混用執(zhí)行可能如下圖:
真是一種完美的解決方案,可以在線上起來。
寫在后面
參考文章列表:
Redis RDB持久化詳解(原理+配置策略) 。
總結(jié)
以上是生活随笔為你收集整理的redis之AOF和RDB持久化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 好佳居软装十大品牌 掌握新中式软装风格
- 下一篇: 锈永不磨灭,让末日来得更酷!