Redis支持的兩種持久化備份方式(RDB & AOF)
redis支持兩種持久化方式,一種是RDB,一種是AOF。
RDB是根據指定的規則定時將內存中的數據備份到硬盤上,AOF是在每次執行命令后命令本身記錄下來,所以RDB的備份文件是一個二進制文件,而AOF的備份文件是一個文本文件。
1. RDB方式
RDB的備份是通過快照來完成的,當符合設定的條件時redis會將內存中的所有數據自動生成一份副本保存到硬盤上,這個保存的過程就是快照。
1.1 根據配置規則自動執行快照
這個條件在配置文件中指定,由兩個參數所定義:時間窗口M和改動的鍵個數N,每當時間M內改動的鍵個數大於N時,則觸發快照備份。

可以同時存在多個快照條件,條件之間是或的關系,也就是說只要有一個條件被觸發就會執行快照備份。
save 900 1 : 在15分鍾內有至少一個鍵被修改則觸發。
save 300 10 : 在5分鍾內至少有10個鍵被修改則觸發。
sae 60 10000 : 在一分鍾內有10000個鍵被修改則觸發。
1.2 用戶執行SAVE或者BGSAVE命令
save命令會讓redis同步地執行快照操作,在快照執行的時候會阻塞所有來自客戶端的請求,當數據庫中的數據比較多時備份時間可能就比較長,就會導致服務器長時間無響應,所以此項在生產環境應該慎用。
需要手動執行快照備份的話應該使用bgsave命令,bgsave命令可以在后台異步的執行備份操作,在備份快照的同時服務器仍然能夠相應客戶端的請求。
既然bgsave那么好,為毛還要save呢?
save可以一直阻塞等到結果,但是因為bgsave是多線程,在執行bgsave的時候只是啟動一個線程去備份,我們並不能確定備份到底有沒有成功呢?當指定bgsave的時候總是返回OK,這個OK表示的是開始執行快照操作並不是快照操作執行成功,要想知道快照是否執行成功,可以通過lastsave命令獲取最近一次成功執行快照的時間,返回結果是一個unix時間戳。

1.3 執行FLUSHALL命令
當執行flushall的時候redis會清空當前倉庫的所有數據,只要自動快照條件不為空的話在清空之前就要執行一次備份,當沒有定義快照觸發條件的時候執行flushall不會執行備份。
1.4 執行復制時
當設置了主從模式時,redis會在初始化時自動進行快照。
1.5 快照的原理
redis默認會將快照放到當前進程工作目錄的dump.db文件中,可以通過配置dir和dbfilename兩個參數來指定要保存到的路徑和文件名。


為了節省空間,RDB文件是經過壓縮的,在硬盤上的占用空間會小於在內存中的占用空間,可以通過rdbcompression參數來禁用掉壓縮(可節省些許cpu占用吧)

rdb快照備份的過程(copy-on-write):
1. redis用fork函數復制一份當前進程的副本。
2. 父進程繼續接受客戶端發來的命令,子進程開始將內存中的數據寫到硬盤的臨時文件。
3. 當子進程備份完的時候將子進程和父進程的數據合並。
(沒看過源代碼,上面抄來的... = = )
注: copy-on-write是一種比較常用的備份策略。
2. AOF(Append Only File)方式
aof一般用於對數據丟失容忍度不高的情況下,用於對數據保存要求較高的場景。
2.1 開啟AOF
默認情況下redis是沒有開啟aof的,使用appendonly來開啟(appendonly yes):

可以通過appendfilename來指定aof文件的名字,默認的名字是【appendonly.aof】:

2.2 AOF的實現
aof文件以純文本的形式記錄了redis執行的命令,它只是傻傻的把執行過的命令往aof文件中添加並不知道添加的是個什么,這樣就可能存在一個問題,比如下面連着的兩條命令:
set foo bar
set foo baar
在aof文件中會忠實的記錄下整個改變的過程,而不是機智的只存儲一個set foo baar。
這樣子的話aof文件中就可能會存在冗余命令,所以可以設定一個觸發條件,設定每到一定條件時就讓redis優化aof文件,優化aof文件的策略是與之前aof的內容無關,而是跟當前內存中的數據有關(在內存中都已經不存在的命令沒有存在必要了,對於已經存在的只保留最后一次的操作就可以啦),進行設定的參數:

auto-aof-rewrite-percentage : 當前的aof文件超過上一次重寫時大小的百分之多少時再次進行重寫,如果之前沒有重寫過,則以啟動時的aof文件大小為依據。
auto-aof-rewrite-min-size : 限制允許重寫aof文件的最小的大小,比如當aof文件很小的時候有冗余也沒關系的,我們就不要再去抽出資源來重寫它啦,這個是aof文件小於64M則不會進行重寫。
2.3 同步硬盤數據
每次同步數據庫的內容時redis都會將命令記錄到aof文件中,但是事實上我們都知道硬盤是有一個寫緩沖區的,要寫的東西並不會立即就寫到硬盤上而是現在硬盤的緩沖區內待一會兒,等到攢夠了人頭再“拼車”一起寫入硬盤,在默認情況下操作系統每30秒會執行一次同步操作,會將硬盤緩沖區的內容真正的寫入到硬盤,但是在這30秒內如果發生了什么人力不可抗拒因素啥的這數據可是就丟了哇,我們用aof就是為了盡量不丟失數據,所以有一個選項appendfsync用來指定同步的策略:
always : 表示每次都會寫入硬盤,這是最安全也是最慢的方式(請確保丫硬盤夠給力....)。
everysec : 每秒同步一次(默認)
no : 不會主動進行同步,讓操作系統看着辦吧,操作系統默認的是每30秒將硬盤緩沖區內的數據同步到的硬盤一次。
RDB和AOF可以同時配置的,當同時開啟的時候啟動的時候redis會加載AOF文件,因為通常情況下AOF持久化保存的數據更完整一些。
參考資料:
1. 《redis入門指南》 第二版
