Redis 笔记(14)— 持久化及数据恢复(数据持久方式 RDB 和 AOF、数据恢复、混合持久化)
1. 持久化
所謂持久化是指將數據從內存中以某種形式同步到硬盤中,在 Redis 重啟后能夠根據硬盤中的記錄恢復數據。Redis 持久化有兩種方式,分別為 RDB(redis data base) 【快照】方式 和 AOF(append only file ) 【日志】方式。
Redis 的持久化機制有兩種,分別為:
- 快照
RDB,快照是一次全量備份,是內存數據的二進制序列化形式,在存儲上非常緊湊; - 日志
AOF,日志是連續的增量備份,日志記錄的是內存數據修改的指令記錄文本;
AOF 日志在長期的運行過程中會變的無比龐大,數據庫重啟時需要加載 AOF 日志進行指令重放,這個時間就會無比漫長。所以需要定期進行 AOF 重寫,給 AOF 日志進行瘦身。
兩者區別:
-
RDB持久化是指在指定的時間間隔內將內存中的數據集快照寫入磁盤,實際操作過程是fork一個子進程,先將數據集寫入臨時文件,寫入成功后,再替換之前的文件,用二進制壓縮存儲。 -
AOF持久化以日志的形式記錄服務器所處理的每一個寫、刪除操作,查詢操作不會記錄,以文本的方式記錄,可以打開文件看到詳細的操作記錄。
2. RDB
2.1 RDB 【快照】方式
RDB 持久化是 Redis 的默認支持,無需進行配置。RDB 是指在指定的時間間隔內將內存中的數據集快照寫入磁盤。當符合一定規則時,Redis 自動將內存中的所有數據生成一份副本并存儲到硬盤上。分為以下四種情況:
-
根據配置規則自動進行快照
SAVE 900 1 SAVE 300 10 SAVE 60 1000SAVE 900 1表示 900s 內有一個或一個以上的鍵被更改則進行快照配置文件中。 -
用戶執行
SAVE或BGSAVE命令(1)
SAVE命令Redis會同步的進行快照操作,在快照執行過程中會阻塞所有來自客戶端請求。(2)
BGSAVE命令Redis會在后臺異步地進行快照操作,在快照執行過程服務端可以繼續響應來自客戶端的請求。具體操作是Redis進程執行fork操作創建子進程,RDB持久化過程由子進程負責,完成后自動結束。阻塞只發生在fork階段,一般時間很短。建議使用。 -
執行
FLUSHALL命令只要快照配置條件不為空,執行該命令時就會執行一次快照操作;而當沒有定義快照條件時,即使執行該命令也不會執行快照操作。
-
執行復制
replication即使沒有定義自動快照條件,且沒有手動執行過快照操作,進行復制操作時也會進行自動快照。
2.2 RDB 【快照】原理
Redis 在 RDB 持久化時會調用 glibc 的函數 fork 產生一個子進程,快照持久化完全交給子進程來處理,父進程繼續處理客戶端請求。子進程剛剛產生時,它和父進程共享內存里面的代碼段和數據段。這是 Linux 操作系統的機制,為了節約內存資源,所以盡可能讓它們共享起來。在進程分離的一瞬間,內存的增長幾乎沒有明顯變化。
用 Python 語言描述進程分離的邏輯如下。fork 函數會在父子進程同時返回,在父進程里返回子進程的 pid,在子進程里返回零。如果操作系統內存資源不足,pid 就會是負數,表示 fork 失敗。
pid = os.fork()
if pid > 0:handle_client_requests() # 父進程繼續處理客戶端請求
if pid == 0:handle_snapshot_write() # 子進程處理快照寫磁盤
if pid < 0:# fork error
子進程做數據持久化,它不會修改現有的內存數據結構,它只是對數據結構進行遍歷讀取,并且保存過時的數據,然后序列化寫到磁盤中。但是父進程不一樣,它必須持續服務客戶端請求,然后對內存數據結構進行不間斷的修改。
這個時候就會使用操作系統的 COW(Copy On Write) 機制來進行數據段頁面的分離。數據段是由很多操作系統的頁面組合而成,當父進程對其中一個頁面的數據進行修改時,會將被共享的頁面復制一份分離出來,然后對這個復制的頁面進行修改。這時子進程相應的頁面是沒有變化的,還是進程產生時那一瞬間的數據。
隨著父進程修改操作的持續進行,越來越多的共享頁面被分離出來,內存就會持續增長。但是也不會超過原有數據內存的 2 倍大小。另外一個 Redis 實例里冷數據占的比例往往是比較高的,所以很少會出現所有的頁面都會被分離,被分離的往往只有其中一部分頁面。每個頁面的大小只有 4K,一個 Redis 實例里面一般都會有成千上萬的頁面。
子進程因為數據沒有變化,它能看到的內存里的數據在進程產生的一瞬間就凝固了,再也不會改變,這也是為什么 Redis 的持久化叫「快照」的原因。接下來子進程就可以非常安心的遍歷數據了進行序列化寫磁盤了。
3. AOF
3.1 AOF 【日志】方式
該機制將以日志的形式記錄服務器所處理的每一個寫操作,在 Redis 服務器啟動之初會讀取該文件來重新構建數據庫,以保證啟動后數據庫中的數據是完整的。
- 默認關閉,通過
appendonly yes可開啟 - 開啟后,每執行一條更改數據庫中的命令時,
Redis都會將該命令寫入硬盤的AOF文件 - 達到一定條件時,
Redis會自動重寫AOF文件
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
- 啟動時
Redis會逐個執行AOF文件中的命令將硬盤中的數據載入到內存中 appendfsync everysec通過配置文件中的該配置項,可使硬盤緩存中的數據每 1s 同步一次到真正的硬盤中
3.2 AOF 【日志】原理
事實上由于操作系統緩存機制,數據并沒有真正寫入硬盤,而是進入系統硬盤緩存。AOF 日志是以文件的形式存在的,當程序對 AOF 日志文件進行寫操作時,實際上是將內容寫到了內核為文件描述符分配的一個內存緩存中,然后內核會異步將臟數據刷回到磁盤的。
這就意味著如果機器突然宕機,AOF 日志內容可能還沒有來得及完全刷到磁盤中,這個時候就會出現日志丟失。那該怎么辦?
Linux 的 glibc 提供了 fsync(int fd) 函數可以將指定文件的內容強制從內核緩存刷到磁盤。只要 Redis 進程實時調用 fsync 函數就可以保證 aof 日志不丟失。但是 fsync 是一個磁盤 IO 操作,它很慢!如果 Redis 執行一條指令就要 fsync 一次,那么 Redis 高性能的地位就不保了。
所以在生產環境的服務器中,Redis 通常是每隔 1s 左右執行一次 fsync 操作,周期 1s 是可以配置的。這是在數據安全性和性能之間做了一個折中,在保持高性能的同時,盡可能使得數據少丟失。
Redis 提供了 bgrewriteaof 指令用于對 AOF 日志進行瘦身。其原理就是開辟一個子進程對內存進行遍歷轉換成一系列 Redis 的操作指令,序列化到一個新的 AOF 日志文件中。序列化完畢后再將操作期間發生的增量 AOF 日志追加到這個新的 AOF 日志文件中,追加完畢后就立即替代舊的 AOF 日志文件了,瘦身工作就完成了。
4. 數據恢復
4.1 RDB 方式
RDB 方式的持久化的數據恢復不需太多操作,只要將備份文件放入 Redis 的安裝目錄,啟動即可。Redis 會自動加載文件至內存。在加載過程中會一直處于阻塞狀態。
優點:
- 整個數據庫只包含一個備份文件。容易恢復和存儲。
- 方便復制和轉移。
- 相比于
AOF,數據集很大的情況下,RDB的啟動效率更高。 - 性能最大化。對于
Redis的服務進程而言,在開始持久化時,它唯一需要做的只是fork出子進程,之后再由子進程完成這些持久化的工作,這樣就可以極大的避免服務進程執行操作。
缺點:
- 如果想最大限度避免數據丟失,
RDB不是一個好選擇,如果系統在持久化期間出現宕機,沒有寫入磁盤的數據都會丟失。 RDB通過fork子進程來協助完成持久化,如果數據集較大,會導致服務器停止一些時間。
4.2 AOF 方式
與 RDB 一樣,重啟 Redis,Redis 會自動加載 AOF 文件,實現數據恢復。
優點:
AOF的數據安全性和同步性比RDB形式高。默認為每秒同步一次,如果設置為每操作同步一次,則數據會實現完全同步。AOF文件是通過追加的形式生成的。如果最后一次寫入出現異常也不會影響之前的文件數據。AOF文件具有清晰可讀的文件格式,如果我們錯誤的寫入了命令,可以立馬關閉,在重寫沒進行時,先進入文件中,去掉寫錯的命令。
缺點:
AOF占用的空間比RDB大。AOF的同步速度比RDB慢。
5 混合持久化
重啟 Redis 時,我們很少使用 rdb 來恢復內存狀態,因為會丟失數據,因為 rdb 不是實時存儲數據的。我們通常使用 AOF 日志重放,但是重放 AOF 日志性能相對 rdb 來說要慢很多,這樣在 Redis 實例很大的情況下,啟動需要花費很長的時間。
Redis 4.0 為了解決這個問題,帶來了一個新的持久化選項——混合持久化。將 rdb 文件的內容和增量的 AOF 日志文件存在一起。這里的 AOF 日志不再是全量的日志,而是自持久化開始到持久化結束的這段時間發生的增量 AOF 日志,通常這部分 AOF 日志很小。
于是在 Redis 重啟的時候,可以先加載 rdb 的內容,然后再重放增量 AOF 日志就可以完全替代之前的 AOF 全量文件重放,重啟效率因此大幅得到提升。
6. 如何選擇
如果對數據的完整性要求不是極高,可以丟失一點數據,那選擇 RDB 是最好的。RDB 無論是備份方便性和恢復速度都高于 AOF,同時可以避免 AOF 的一些 bug。
如果對數據的完整性要求極高,請選擇 AOF 形式。
參考:
https://juejin.cn/book/6844733724618129422/section/6844733724714614797
總結
以上是生活随笔為你收集整理的Redis 笔记(14)— 持久化及数据恢复(数据持久方式 RDB 和 AOF、数据恢复、混合持久化)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2022-2028年中国涤纶市场投资分析
- 下一篇: Redis 笔记(15)— 管道 pip