進階的Redis之數據持久化RDB與AOF
大家都知道,Redis之所以性能好,讀寫快,是因為Redis是一個內存數據庫,它的操作都幾乎基於內存。但是內存型數據庫有一個很大的弊端,就是當數據庫進程崩潰或系統重啟的時候,如果內存數據不保存的話,裏面的數據就會丟失不見了。這樣的數據庫並不是一個可靠的數據庫。
所以數據的持久化是內存型數據庫的重中之重。它不僅提供數據保存硬盤的功能,還可以借此用硬盤容量擴展數據存儲空間,使得Redis的可以存儲超過機器本身內存大小的數據。
Redis對於數據持久化提供了兩種持久化的方案,RDB與AOF。它們的原理和使用場景都大不相同,下面我們來詳細地了解下。
RDB——數據快照(Snapshot)
RDB,提供一個某個時間點的數據的Snapshot,保存在RDB文件中。它可以通過SAVE/BGSAVE
Redis也可以通過加載RDB文件,把數據從磁盤加載讀取到Redis中。
RDB文件創建
連上Redis,設值一些值,然後執行SAVE
命令。
然後可以查看下redis.conf的持久化工作目錄。進入目錄可以看到保存了一個dump.rdb文件。該文件是一個二進制文件,無法直接正常打開。
至於SAVE/BGSAVE
的區別,就是前置是阻塞執行,此時服務不會接受請求,後者是Fork一個子進程出來,由該進程去執行保存RDB文件的操作,不影響用戶請求。
P.S. Redis是單進程的,所以BGSAVE
只能Fork一個子進程,而不是創建一個線程處理。
以上是手動執行的過程。但在生產我們很少會手動登上服務去執行操作,所以更多的時候是依賴Redis的配置,定時保存RDB文件。
打開redis.conf
配置文件,找到SNAPSHOTTING的配置,Save Point的設置。
圖中的配置意思是,當至少有一個key變更時,900秒後會執行一次SAVE。其他配置同理,有10次變更,300秒後保存一次.....
在Redis中,這個自動保存RDB的功能是默認開啟的。
RDB文件加載
先kill掉Redis進程,再重新啟動Redis Server,會發現日誌會有這樣的一行,
並且Redis中,依然有之前設置的三個值。說明Redis在啟動的時候,會加載數據初始化。
不過,這裏加載的初始化數據不一定是RDB的。如果Redis開啟了AOF,會優先從AOF初始化數據,否則才會加載RDB的數據。
(出處《Redis設計與實現》——黃健宏)
RDB優缺點
優點:
- RDB是某一時間點的快照,是一個緊湊的單文件,更多用於數據備份。可以按每小時或每日來備份,方便從不同的版本恢復數據。
- 單文件容易傳輸到遠程服務做故障恢復。
- RDB可以Fork子進程進行持久化,使Redis可以更好地處理用戶請求
- 在大量數據的情況下,RDB相比較於AOF會更快的加載。
缺點:
- 如果Redis不及時保存RDB文件,會造成數據的丟失。例如系統突然斷電,但未來得及保存數據。即使你設置更多的Save point,也無法保證100%的數據不丟失。
- RDB經常需要fork子進程去執行,但如果再大量數據的情況下,這個fork操作會非常耗CPU資源的。對比AOF雖然也是fork,但是它的數據保存處理是可以控制的,不需要全量保存。
AOF——日誌追加(Append-Only)
Redis的另外一種持久化方案就是AOF,Append Only File。AOF相當於一個操作的日誌記錄,每次對於數據的變更都會記錄追加到AOF日誌。當服務啟動的時候就會讀這些操作日誌,重新執行一次操作,從而恢復原始數據。
AOF啟用
AOF默認是關閉的。打開redis.conf配置文件,找到appendonly no
改成appendonly yes
。
AOF和RDB是可以共存的,只要保存的文件名不沖突。
AOF fsync同步規則
配置文件往下拉,看到fsync
的配置。
fsync()是一個系統調用函數,告訴操作系統把數據寫到硬盤上,而不是緩存更多數據才寫到硬盤。這樣的調用可以及時保存數據到硬盤上。
Redis提供了三種fsync的調用方式
- appendfsync always,每次操作記錄都同步到硬盤上,最低效,最安全。
- appendfsync everysec,每秒執行一次把操作記錄同步到硬盤上。默認選項。
- appendfsync no,不執行fysnc調用,讓操作系統自動操作把緩存數據寫到硬盤上,不可靠,但最快。
AOF文件格式解析
開啟AOF後,會再工作目錄看到appendonly.aof
文件。
在客戶端上執行一些命令後,打開AOF文件,可以觀察到有對應的操作的記錄日誌。
文件解析說明:
- *,表示命令的參數個數,例如
set a 1
是三個參數,所以是*3 - $,表示參數的字節數,例如
set
這個參數是三字節,所以是$3,key值a是一個字節,所以是$1 - 無符號,表示是參數的數據,例如
set
,a
,1
就是具體的數據
日誌重寫
AOF雖然比RDB更可靠,但缺點也是比較明顯的,就是每次寫操作都要把操作日誌寫到文件上,這樣會導致文件非常冗余。
假若你要自增一個計數器100次,如果不重寫,AOF文件就就會有這100次的自增記錄,如INCR a
。如果執行了日誌重寫,那麽文件只會保留set a 100
而不是100條INCR a
。這樣擁有相同的結果,但可以大大減少AOF的文件大小,並且可以讓AOF載入的時候提升載入的效率。
看回redis.conf
配置,有兩項控制rewrite的選項。
- auto-aof-rewrite-percentage 100,當文件增長100%(一倍)時候,自動重寫。
- auto-aof-rewrite-min-size 64mb,日誌重寫最小文件大小,如果小於該大小,不會自動重寫。
來實驗一下重寫的結果,我們先設定一個a值,然後自增多次,查看AOF文件內容。裏面有很多INCR的語句記錄
然後我們手動執行下BGREWRITEOF
,執行日誌重寫。
可以看到,多個incr語句,變成了一個set a 6
語句,減少了5個incr a
語句的操作日誌。
AOF優缺點
優點:
- AOF可以設置 完全不同步、每秒同步、每次操作同,默認是每秒同步。因為AOF是操作指令的追加,所以可以頻繁的大量的同步。
- AOF文件是一個值追加日誌的文件,即使服務宕機為寫入完整的命令,也可以通過redis-check-aof工具修復這些問題。
- 如果AOF文件過大,Redis會在後臺自動地重寫AOF文件。重寫後會使AOF文件壓縮到最小所需的指令集。
- AOF文件是有序保存數據庫的所有寫入操作,易讀,易分析。即使如果不小心誤操作數據庫,也很容易找出錯誤指令,恢復到某個數據節點。例如不小心FLUSHALL,可以非常容易恢復到執行命令之前。
缺點
- 相同數據量下,AOF的文件通常體積會比RDB大。因為AOF是存指令的,而RDB是所有指令的結果快照。但AOF在日誌重寫後會壓縮一些空間。
- 在大量寫入和載入的時候,AOF的效率會比RDB低。因為大量寫入,AOF會執行更多的保存命令,載入的時候也需要大量的重執行命令來得到最後的結果。RDB對此更有優勢。
如何選擇
以上已經基本了解過RDB和AOF的使用、基本原理以及對應的優缺點。那麽在實際當中,我們到底怎麽去選擇用哪種持久化方式呢?
一般來說,不考慮硬盤大小,最安全的做法是RDB與AOF同時使用,即使AOF損壞無法修復,還可以用RDB來恢復數據。
如果Redis的數據在你的服務中並不是必要的數據,例如只是當簡單的緩存,沒有緩存也不會造成緩存雪崩。說明數據的安全可靠性並不是首要考慮範圍內,那麽單獨只使用RDB就可以了。
不推薦單獨使用AOF,因為AOF對於數據的恢復載入來說,比RDB慢。並且Redis官方也說明了,AOF有一個罕見的bug。出了問題無法很好的解決。所以使用AOF的時候,最好還是有RDB作為數據備份。
根據官方的意願描述,在未來可能會有一種RDB與AOF相結合的持久化模型。到時Redis持久化就不再如此麻煩費勁了,我們拭目以待吧。
更多技術文章、精彩幹貨,請關註
博客:zackku.com
微信公眾號:Zack說碼
進階的Redis之數據持久化RDB與AOF