1. RDB
????????RDB 持久化是把當前進程數據生成快照保存到硬盤的過程,觸發 RDB 持久化過程分為手動觸發和 自動觸發,存儲的是二進制數據。
1.1 手動觸發
使用 save 和 bgsave 命令觸發:
- save:Redis服務主進程阻塞式執行持久化操作,直到RDB過程結束,在此期間 Redis 服務端無法執行客戶端的命令,持久化數據量大的情況下,會導致主進程長時間阻塞,使用較少;
- bgsave:后臺執行持久化操作,Redis主進程使用 fork 創建子進程,RDB持久化過程由子進程負責執行,阻塞時間較短,只發生在fork階段;
1.2 自動觸發
- 自動觸發在 Redis 配置文件 redis.conf 中進行配置, 比如:如 "save m n" 表示 m 秒內數據集發生了 n 次修改,自動 RDB 持久化。
- 從節點進行全量復制操作時,主節點?動進行 RDB 持久化,隨后將 RDB ?件內容發送給從結點。
- 執行?shutdown 命令關閉 Redis 時,也會執行RDB 持久化。
1.3 持久化流程
RDB 是快照式的數據保存,常見的持久化操作都是在 后臺進行的(bgsave)流程如下:
- ?檢查是否已有持久化進程運行?,如果有就直接返回;
- Redis 主進程調用?
fork()
創建子進程,fork 過程會短暫阻塞主線程(阻塞時間取決于內存大小和系統性能),且由于 父進程創建的子進程和父進程共享數據,詳細介紹可見【Linux進程】進程地址空間-CSDN博客 - 父進程 fork 完成后,bgsave 命令返回 "Background saving started" 信息并不再阻塞父進程,可以繼續響應其他命令。
- 子進程創建 RDB ?件,根據父進程內存生成臨時快照文件,完成后對原有文件進行原子替換。
- 進程發送信號給父進程示完成,父進程更新統計信息
1.4 RDB文件
RDB 文件默認在 /var/lib/redis/ 下,文件名通過 dbfilename 配置(默認為 dump.rdb)指定;config set dir {newDir} 和 config set dbfilename??{newFilename} 運行期間動態執行,當下次運行時 RDB 文件會保存到新目錄
Redis 默認采? LZF 算法對生成的 RDB ?件做壓縮處理,壓縮后的?件遠遠小于內存大小,默認開啟,可以通過參數 config set rdbcompression {yes|no} 動態修改。
注意:如果 Redis 啟動時加載到損壞的 RDB 文件會拒絕啟動。這時可以使用?Redis 提供的 redischeck-dump ?具檢測 RDB 文件并獲取對應的錯誤報告。
1.5 優缺點
優點:
- RDB 是?個緊湊壓縮的?進制?件,存儲 Redis 在某個時間點上的數據快照。非常適用于備份,全量復制等場景;
- 數據恢復速度比 AOF 快;
缺點:
- 無法實時持久化(每次都會fork創建子進程,該操作屬于重量級操作,頻繁創建會嚴重影響性能);
- RDB 文件使用特定?進制格式保存,Redis 版本演進過程中有多個 RDB 版本,兼容性可能有風險。
2. AOF
AOF(Append Only File)持久化:以獨立日志的方式記錄每次的寫命令,重啟時再重新執行?AOF?文件中的命令達到恢復數據的目的。AOF 的主要作用是解決了數據持久化的實時性,目前已經是 Redis 持久化的主流方式。
寫入的數據可讀性也相對較好,比如:set hello world
那么在文件中就會追加以下文本:
*3\r\n$3\r\nset\r\n$5\r\nhello\r\n$5\r\nworld\r\n
2.1 配置 AOF
開啟 AOF 功能需要設置配置:appendonly yes,默認不開啟。AOF 文件名通過?appendfilename 配置(默認是 appendonly.aof)設置。保存目錄同 RDB 持久化方式?致,通過 dir?配置指定;
2.2 工作流程
1. 所有的寫入命令會追加到 aof_buf(緩沖區)中。
2. AOF 緩沖區根據對應的策略向硬盤做同步操作。?
3. 隨著 AOF文件越來越大,需要定期對 AOF 文件進行重寫,達到壓縮的目的。
4. 當 Redis 服務器啟動時,可以加載 AOF 文件進行數據恢復。
2.3 文件同步
由于存在緩沖區的緣故,對于緩沖區同步到文件主要分為三種策略:
可配置值 | 說明 | 數據安全性 | 性能影響 | 適用場景 |
---|---|---|---|---|
??always?? | 每次寫入命令后立即調用? | 最高 | 性能最低(頻繁磁盤 I/O) | 對數據一致性要求極高的場景(如金融交易) |
??everysec?? | 命令先寫入內存緩沖區( | 中等 | 性能與安全的平衡(推薦默認值) | 大多數生產環境 |
??no?? | 命令寫入? | 最低 | 性能最高(但可能丟失更多數據) | 可容忍少量數據丟失的高吞吐場景 |
write 和 fsync說明:
write:write會觸發操作系統的延遲寫機制,write 操作在寫入系統緩沖區后就會立即返回;同步到硬盤操作依賴于系統調度機制;如果數據在操作系統緩沖區內還沒落盤,此時發生斷電或系統宕機,那么緩沖區數據就會丟失;
fsync:針對單個文件操作,做強制硬盤同步,fsync 將阻塞直到數據寫入到硬盤;
2.4 重寫機制
隨著命令不斷寫入 AOF,文件會越來越大,為了解決這個問題,Redis 引? AOF 重寫機制壓縮? 件體積。
為什么會越來越大?比如:
set k1 v1
set k2 v2
del k1
數據實際只存儲了 k2?- v2,但存儲了三條命令;重寫機制可以認為是對 AOF 文件的整理;比如:
- 進程內已超時的數據不再寫入文件。
- 舊的 AOF 中的無效命令,例如 del、hdel、srem 等重寫后將會刪除,只需要保留數據的最終版 本。
- 多條寫操作合并為?條,例如 lpush list a、lpush list b、lpush list c 可以合并為 lpush list a b?c。
AOF 重寫過程可以手動動觸發和自動觸發:
- 手動觸發:調用?bgrewriteaof 命令。?
- 自動觸發:根據 auto-aof-rewrite-min-size 和 auto-aof-rewrite-percentage 參數確定?動觸發時機
auto-aof-rewrite-min-size:表示觸發重寫時 AOF 的閾值,默認為 64MB。
auto-aof-rewrite-percentage:代表當前 AOF 占用大小相比較上次重寫時增加的比例。
2.5 重寫流程
1. 執行重寫請求,如果當前進程正在執行 AOF 重寫,請求不執行。如果當前進程正在執行 bgsave 操作,重寫命令延遲到 bgsave 完成之后再執行。
2. 父進程執行 fork 創建子進程
3. 重寫
????????3.1 主進程 fork 之后繼續響應其他命令,后續所有修改操作會被記錄到 aof_buf 中,根據策略進行落盤;
????????3.2 子進程只有fork之前的所有內存數據,在子進程重寫的期間,父進程需要將修改操作寫入?AOF 重寫緩沖區中;
4. 子進程根據內存快照,讀取內存中數據,整理后寫入到新的AOF文件中;
5. 完成重寫,進行AOF文件替換
????????5.1 新文件寫入后,子進程發送信號給父進程。
????????5.2 父進程把 AOF 重寫緩沖區內臨時保存的命令追加到新 AOF ?件中。
????????5.3 用新 AOF 文件替換舊 AOF 文件。
3. 啟動時數據恢復
當 Redis 啟動時,會根據 RDB 和 AOF 文件的內容,進行數據恢復;
??當 Redis 重啟時,如果 AOF 文件和 RDB 文件同時存在,Redis 會優先使用 AOF 文件進行數據恢復?;
??步驟?? | ??行為?? |
---|---|
??檢查 AOF 是否啟用?? | 如果? |
??AOF 文件不存在/損壞?? | 如果 AOF 文件不可用(如文件損壞),則嘗試加載 RDB 文件作為備用恢復。 |
??AOF 和 RDB 均未啟用?? | 啟動一個空數據集(無持久化數據)。 |