談談Redis 的持久化策略?
參考文章:
- Redis 持久化機制演進與百度智能云的實踐
Redis
的確是將數據存儲在內存的,但是也會有相關的持久化機制將內存持久化備份到磁盤,以便于重啟時數據能夠重新恢復到內存中,避免數據丟失的風險。而Redis
持久化機制有三種:AOF
、RDB
、混合型持久化(4.x版本后提供)
-
RDB持久化
關閉 RDB 持久化只需要將 save 保存策略注釋掉即可
RDB持久化的方式有兩種:
-
手動觸發(分為手動 save 和手動 bgsave)
-
手動save:阻塞當前 Redis,直到持久化完成,可能造成長時間阻塞,線上不建議使用。?
-
手動bgsave:Redis 進程執行
fork
創建子進程進行持久化,阻塞事件很短。在執行Redis-cli shutdown
關閉Redis
服務時或執行flushall
命令時,如果沒有開啟AOF
持久化,自動執行bgsave
-
-
被動觸發(以下四種情況會被動觸發)
-
達到了在 redis.conf 中配置被動觸發的條件,會觸發 bgsave 生成 rdb 文件
Redis 中 save 操作的配置:從右向左條件主鍵變弱,如果60s發生了10000次寫操作,就進行持久化,如果沒有達到,在300s時,如果有100次寫操作就會持久化,如果沒有達到在3600s,如果有一次寫操作就會持久化
-
主從復制時,從節點需要全量同步主節點的數據,會觸發 bgsave
-
執行
debug reload
命令重新加載 redis 時,會觸發 bgsave -
執行
shutdown
命令時,如果沒有開啟 aof 持久化,會觸發 bgsave
-
?
bgsave子進程工作原理:
由子進程繼承父進程所有資源,且父進程不能拒絕子進程繼承,bgsave子進程先將內存中的全量數據copy到磁盤的一個
RDB臨時文件
,持久化完成后將該臨時文件替換原來的dump.rdb
文件。如果持久化過程中出現了新的寫請求,則系統會將內存中發生數據修改的物理塊copy出一個副本,bgsave 子進程會把這個副本數據寫入 RDB 文件,在這個過程中,主線程仍然可以直接修改原來的數據,
fork
使用了寫時復制技術(Copy-On-Write)
。?
操作系統中的寫時復制技術:
目的:是避免不必要的內存拷貝。
在Linux系統中,調用
fork
系統調用創建子進程時,并不會把父進程所有占用的內存頁復制一份,而是與父進程共用相同的內存頁,而當子進程或者父進程對內存頁進行修改時才會進行復制 —— 這就是著名的寫時復制
機制。那么bgsave中的寫時復制技術即如果在持久化過程中,寫入了新的數據,此時再去將元數據重新拷貝一份,進行修改。
?
優點:
- 使用單獨子進程持久化,保證 redis 高性能。
- RDB 持久化存儲壓縮的二進制文件,適用于備份、全量復制,可用于災難備份,同時
RDB
文件的加載速度遠超于AOF
文件。
缺點:
- 沒有實時持久化,可能造成數據丟失。
- 備份時占用內存,因為
Redis
在備份時會獨立創建一個子進程,將數據寫入到一個臨時文件(需要的內存是原本的兩倍) RDB
文件保存的二進制文件存在新老版本不兼容的問題。
-
-
AOF持久化
默認AOF沒有開啟,可在
redis.conf
中配置Redis7發生了重大變化,原來只有一個appendonly.aof文件,現在具有了三類多個文件:
- 基本文件:RDB格式或AOF格式。存放RDB轉為AOF當時內存的快照數據。該文件可以有多個。
- 增量文件:以操作日志形式記錄轉為AOF后的寫入操作。該文件可以有多個。
- 清單文件:維護AOF文件的創建順序,保證激活時的應用順序。該文件只可以有1個。
?
aof 文件中存儲的
resp 協議數據格式
,如果執行命令set a hello
,aof文件內容如下:(*3代表有3條命令,$5代表有5個字符)
*3 $3 set $1 a $5 hello
AOF持久化時,其實是先寫入緩存中,之后再同步到磁盤中,同步策略有三種:
appendfsync always
:每次寫入都同步到磁盤,最安全,但影響性能。appendfsync everysec
(推薦、默認配置):每秒同步一次,最多丟失1秒的數據。appendfsync no
:Redis
并不直接調用文件同步,而是交給操作系統來處理,操作系統可以根據buffer
填充情況/通道空閑時間等擇機觸發同步;這是一種普通的文件操作方式。性能較好,在物理服務器故障時,數據丟失量會因OS
配置有關。
優點:
- 數據丟失風險較低,后臺線程處理持久化,不影響客戶端請求處理的線程。
缺點:
- 文件體積由于保存的是所有命令會比
RDB
大上很多,而且數據恢復時也需要重新執行指令,在重啟時恢復數據的時間往往會慢很多。
AOF的重寫(Rewrite)機制:
-
為了防止AOF文件太大占用大量磁盤空間,降低性能,Redis引入了Rewrite機制對AOF文件進行壓縮
Rewrite就是對AOF文件進行重寫整理。當開啟Rewrite,主進程redis-server創建出一個子進程bgrewriteaof,由該子進程完成rewrite過程。
首先會對現有aof文件進行重寫,將計算結果寫到一個臨時文件,寫入完畢后,再重命名為原aof文件,進行覆蓋。
?
配置AOF重寫頻率
# auto‐aof‐rewrite‐min‐size 64mb //aof文件至少要達到64M才會自動重寫,文件太小恢復速度本來就很快,重寫的意義不大 # auto‐aof‐rewrite‐percentage 100 //aof文件自上一次重寫后文件大小增長了100%則再次觸發重寫
AOF的持久化流程圖:
?
-
混合持久化開啟
默認開啟,即AOF持久化的基本文件時的基本文件是RDB格式的。(必須先開啟aof)
混合持久化重寫aof文件流程:aof 在重寫時,不再將內存數據轉為 resp 數據寫入 aof 文件,而是將之前的內存數據做 RDB 快照處理,將
RDB快照+AOF增量數據
存在一起寫入新的 AOF 文件,完成后覆蓋原有的 AOF 文件。?
Redis重啟加載數據流程:
- 先加載 RDB 數據到內存中
- 再重放增量 AOF 日志,加載 AOF 增量數據
優點:
- 結合了 RDB 和 AOF,既保證了重啟 Redis 的性能,又降低數據丟失風險
缺點:
- AOF 文件中添加了 RDB 格式的內容,使得 AOF 文件的可讀性變得很差;