你說你精通 Redis,你看過持久化的配置嗎?
我們之前介紹了 Redis 五種數據類型的命令 與 配置文件的基本配置 ,今天讓我們從理論和配置兩個層面來揭開 Redis 持久化的神秘面紗。
所謂持久化可以簡單理解為將內存中的數據保存到硬盤上存儲的過程。持久化之后的數據在系統重啟或者宕機之后依然可以進行訪問,保證了數據的安全性。
Redis 有兩種持久化方案,一種是快照方式( SNAPSHOTTING ),簡稱 RDB ;一種是只追加模式( APPEND ONLY MODE ),稱為AOF。接下來讓我們分別了解一下它們的使用與注意事項。
RDB
RDB 為 Redis DataBase 的縮寫,是 Redis 默認的持久化方案。它能夠在指定的時間間隔內將內存數據集快照( snapshot )寫入磁盤,恢復時將快照文件( dump.rdb )讀回內存。
我們先來扒一下配置文件中的 SNAPSHOTTING :
配置文件
save <seconds> <changes>
在給定的 秒數 內,如果對數據庫執行的 寫入操作數 達到設定的值,則將數據同步到數據文件。支持多個條件配合, Redis 默認配置文件中提供了三個條件:
- save 900 1 //900s內有1個更改
- save 300 10 //300s內有10個更改
- save 60 10000 //60s內有10000次更改
注意:若不想用 RDB 方案,可以把 save "" 的注釋打開,上邊三個注釋掉。
stop-writes-on-bgsave-error yes
當 bgsave 出現錯誤時, Redis 是否停止執行寫命令;
- 如果為
yes,則當硬盤出現問題時,Redis將停止接受寫入操作,這樣我們可以及時發現,避免數據的大量丟失;
- no
- Redis
- bgsave
如果已經設置了對 Redis 服務器的正確監視和持久性,即采用了其他手段發現和控制數據完整性,可能希望禁用此功能,以便即使在磁盤、權限等方面出現問題時, Redis 仍能正常工作。
注意:如果后臺保存過程將再次開始工作, Redis 將自動允許再次寫入。
rdbcompression yes
指定存儲到本地數據庫時是否 壓縮 ( Redis 采用 LZF 壓縮)數據,默認為 yes 。如果為了節省 CPU 時間,可以關閉該選項,但會導致數據庫文件變得巨大。
rdbchecksum yes
從 RDB 版本 5 開始,在存儲快照后,還可以使用 CRC64 算法來進行數據校驗, CRC64 校驗放在文件的末尾。開啟之后,保存和加載 RDB 文件時會增加大約 10% 的性能消耗,如果希望獲取到最大的性能提升,可以關閉此功能。
禁用 校驗和 創建的 RDB 文件的校驗和為零,這將告訴加載代碼跳過檢查。
dbfilename dump.rdb
指定本地數據庫文件名,重啟之后自動加載進 內存 ,手動執行 save 命令的話即刻生效。
大坑請注意: flushall 、 shutdown 命令都會清空并提交至 dump.rdb
dir ./
指定本地數據庫存放目錄。
理論
工作方式
- Redis
- dump.rdb
- fork()
RDB 中;
- RDB
- Redis
- RDB
- RDB
- RDB
這種工作方式使得 Redis 可以從寫時復制( copy-on-write )機制中獲益。
如何觸發RDB快照
-
配置文件中默認的快照配置;
- 命令
save(阻塞, 只管保存快照,其他的等待)或者是bgsave(異步)命令,快照同時還可以響應客戶端命令; - 執行
flushall命令,清空數據庫所有數據,意義不大; - 執行
shutdown命令,保證服務器正常關閉且不丟失任何數據,意義也不大。
通過RDB文件恢復數據
在實際開發中,一般會考慮到物理機硬盤損壞的情況,所以我們會選擇備份 dump.rdb 文件。將備份的 dump.rdb 文件拷貝到 redis 的安裝目錄的 bin 目錄下,重啟 redis 服務即可。
優點
RDB是一個非常緊湊的文件,非常適用于數據集的備份;RDB是一個緊湊的單一文件,很方便傳送到另一個遠端數據中心或者亞馬遜的S3(可能加密),非常適用于災難恢復;Redis的主進程不進行I/O操作,確保了極高的性能;- 適合大規模數據的恢復,對于數據的完整性和一致性要求不高的話,
RDB比AOF方式更加高效。
缺點
- 在
Redis意外宕機時,你可能會丟失幾分鐘的數據;
- RDB
- fork
- fork
- Redis
- CPU
- AOF
- fork
AOF
為了解決 RDB 方式在宕機時丟失數據過多的問題,從 1.1 版本開始, Redis 增加了一種 durable 的持久化方式: AOF 。
AOF 是 Append Only File 的縮寫,默認不開啟。 AOF 以日志的形式來記錄每個寫操作,只允許追加文件但不可以改寫文件,當服務器重啟的時候會重新執行這些命令來恢復原始的數據。
我們再來看一下配置文件中的 APPEND ONLY MODE :
配置文件
appendonly no
默認為關閉狀態,改為 yes 打開持久化。 AOF 和 RDB 可以同時啟用而不會出現問題。
appendfilename "appendonly.aof"
文件默認名稱,啟動即創建。加載 先于 dump.rdb 文件
appendfsync
同步策略:系統函數 fsync() 告訴操作系統在磁盤上實際寫入數據。 Redis 支持三種不同的模式
- appendfsync always //每次發生數據變更會被立即記錄到磁盤,性能較差但數據完整性比較好
- appendfsync everysec //默認推薦,異步操作,每秒記錄,如果宕機,有1秒內數據丟失
- appendfsync no //不同步,只有在操作系統需要時在刷新數據
要想了解接下來的配置內容,先得說一下“日志重寫”的原理:
重寫
由于 AOF 采用的是將命令追加到文件末尾的方式,所以隨著寫入命令的不斷增加, AOF 文件的體積會變得越來越大。為避免出現此種情況,新增了重寫機制:可以在不打斷服務客戶端的情況下,對 AOF 文件進行重建( rebuild )。
重寫觸發:通過執行 bgrewriteaof 命令,可以生成一個新的 AOF 文件,該文件包含重建當前數據集所需的 最少 命令。 Redis 2.2 需手動執行該命令, Redis 2.4 則可以通過修改配置文件的方式自動觸發(配置在下邊涉及)。
重寫原理:
Redis執行系統函數fork(),創建一個子進程(與主進程完全一致);- 子進程開始將新
AOF文件的內容寫入到臨時文件; - 對于所有新執行的寫入命令,父進程一邊將它們累積到一個內存緩存中,一邊將這些改動追加到現有
AOF文件的末尾,這樣即使在重寫的中途發生停機,現有的AOF文件也是安全的; - 當子進程完成重寫工作時,它給父進程發送一個信號,父進程在接收到信號之后,將內存緩存中的所有數據追加到新
AOF文件的末尾。 Redis原子地用新文件替換舊文件,之后所有命令都會直接追加到新AOF文件的末尾。
no-appendfsync-on-rewrite no
當我們同時執行主進程的 寫操作 和子進程的 重寫 操作時,兩者都會操作磁盤,而重寫往往會涉及到大量的磁盤操作,這樣就會造成主進程在寫 aof 文件的時候出現阻塞的情形。
為了解決這個問題, no-appendfsync-on-rewrite 參數出場了。
- 如果該參數設置為
no,是最安全的方式,不會丟失數據,但是要忍受阻塞的問題;
- yes
- appendfsync
- no
- redis
- linux
因此,如果應用系統無法忍受延遲,而可以容忍少量的數據丟失,則設置為 yes ;如果應用系統無法忍受數據丟失,則設置為 no 。
auto-aof-rewrite-percentage 100
重寫百分比,默認為上次重寫后 aof 文件大小的一倍。
auto-aof-rewrite-min-size 64mb
重寫觸發的最小值:64mb。
根據 auto-aof-rewrite-min-size 和 auto-aof-rewrite-percentage 參數確定自動觸發時機。 Redis 會記錄上次重寫時的 AOF 大小,默認配置是當 AOF 文件大小是上次 rewrite 后大小的一倍且文件大于 64M 時觸發。
大型互聯網公司一般都是 3G 起步
aof-load-truncated yes
當 AOF 文件被截斷時,即 AOF 文件的最后命令不完整,如果此時啟動 Redis ,會將 AOF 數據加載回內存,此時便會出現問題。
- yes:加載一個截斷的
AOF,Redis服務器開始發出日志,通知用戶該事件; -
no:服務器將中止并出現錯誤,拒絕啟動。
當我們得知 AOF 文件報錯時,可以用以下方法來修復出錯的 AOF 文件:
-
為現有的
AOF文件創建一個備份; -
使用
Redis附帶的redis-check-aof命令,對原來的AOF文件進行修復;-
redis-check-aof –fix -
redis-check-aof --fix appendonly.aof修復命令,殺光不符合規范的語法
-
-
( 可選 )使用
diff -u對比修復后的AOF文件和原始AOF文件的備份,查看兩個文件之間的不同之處; -
重啟
Redis服務器,等待服務器載入修復后的AOF文件,并進行數據恢復。
aof-use-rdb-preamble yes
在重寫 AOF 文件時, Redis 能夠在 AOF 文件中使用 RDB 前導,以加快重寫和恢復速度。啟用此選項后,重寫的 AOF 文件由兩個不同的節組成: RDB file 、 AOF tail
加載 Redis 時,會識別 AOF 文件以 Redis 字符串開頭,并加載帶前綴的 RDB 文件,然后繼續加載 AOF 尾部。
理論
優點
- 數據的完整性和一致性更高,
AOF的持久化通過使用不同的策略,最多丟失1秒的數據; AOF文件是一個只進行追加的日志文件,不需要寫入seek;
- Redis
- AOF
- AOF
AOF 文件記錄的寫入操作以 Redis 協議的格式保存,容易讀懂,容易對文件進行分析;缺點
- 對于相同的數據集來說,
AOF文件的體積通常要大于RDB文件的體積;
- fsync
- AOF
- RDB
在一般情況下,每秒 fsync 的性能依然非常高,而關閉 fsync 可以讓 AOF 的速度和 RDB 一樣快, 即使在高負荷之下也是如此。不過在處理巨大的寫入載入時, RDB 可以提供更有保證的最大延遲時間( latency )。
對比與總結
如何選擇使用哪種持久化方式?
一般來說,如果想達到足以媲美 PostgreSQL 的數據安全性,應該同時使用兩種持久化功能。
如果非常關心數據,但仍然可以承受數分鐘以內的數據丟失,那么可以只使用 RDB 持久化。
由于AOF持久化的實時性更好,即當進程意外退出時丟失的數據更少,因此 AOF 是目前 主流 的持久化方式。
有很多用戶都只使用 AOF 持久化,但我們并不推薦這種方式:因為定時生成 RDB 快照( snapshot )非常便于進行數據庫備份,并且 RDB 恢復數據集的速度也要比 AOF 恢復的速度要快。
AOF和RDB之間的相互作用
在版本號大于等于 2.4 的 Redis 中, BGSAVE 執行的過程中,不可以執行 BGREWRITEAOF 。反過來說,在 BGREWRITEAOF 執行的過程中,也不可以執行 BGSAVE 。這可以防止兩個 Redis 后臺進程同時對磁盤進行大量的 I/O 操作。
如果 BGSAVE 正在執行,并且用戶顯示地調用 BGREWRITEAOF 命令,那么服務器將向用戶回復一個 OK 狀態, 并告知用戶 BGREWRITEAOF 已經被預定執行:一旦 BGSAVE 執行完畢, BGREWRITEAOF 就會正式開始。
當 Redis 啟動時,如果 RDB 持久化和 AOF 持久化都被打開了, 那么程序會優先使用 AOF 文件來恢復數據集,因為 AOF 文件所保存的數據通常是最完整的。
備份redis數據
- cron job
- RDB
- RDB
find 命令來刪除過期的快照;RDB 備份到你的數據中心之外,或者至少是備份到你運行 Redis 服務器的物理機器之外。性能建議
在實際應用時,因為 RDB 文件只用作后備用途,建議只在 slave 上持久化 RDB 文件,而且只需要15分鐘備份一次就夠了,只保留 save 900 1 這條規則。
如果開啟 AOF ,好處是在最惡劣情況下也只會丟失不超過2秒數據,啟動腳本較簡單只 load 自己的 AOF 文件就可以了。代價一是帶來了持續的 IO ,二是 AOF rewrite 的最后將 rewrite 過程中產生的新數據寫到新文件造成的阻塞幾乎是不可避免的。
只要硬盤許可,應該盡量減少 AOF rewrite 的頻率, AOF 重寫的基礎大小默認值 64M 太小了,可以設置到 5G 以上。默認超過原大小的100%時重寫可以改到適當的數值。
如果不開啟 AOF ,僅靠 Master-Slave Replication 實現高可用性也可以。能省掉一大筆 IO ,也減少了 rewrite 時帶來的系統波動。代價是如果 Master/Slave 同時倒掉,會丟失十幾分鐘的數據,啟動腳本也要比較兩個 Master/Slave 中的 RDB 文件,載入較新的那個。


























