Redis持久化

小陳_winwah發表於2023-11-25

Redis持久化

image-20231113213822951

RDB持久化

實現類似照片記錄效果的方式,就是把某一時刻的資料和狀態以檔案的形式寫到磁碟上,也就是快照。這樣一來即使故障當機,快照檔案也不會丟失,資料的可靠性也就得到了保證。這個快照檔案就稱為RDB檔案(dump.rdb),其中,RDB就是Redis DataBase的縮寫。

在指定的時間間隔內將記憶體中的資料集快照寫入磁碟,也就是行話講的Snapshot記憶體快照,它恢復時再將硬碟快照檔案直接讀回到記憶體裡。

Redis的資料都在記憶體中,儲存備份時它執行的是全量快照,也就是說,把記憶體中的所有資料都記錄到磁碟中,一鍋端。

配置檔案

自動觸發:

Redis 6.0.16以前:

在Redis.conf 配置檔案中的SNAPSHOTTING 下配置 save 引數,來觸發 Redis 的 RDB 持久化條件,

比如 “ save m n” 表示在 m 秒內資料集存在 n 次修改時,自動觸發 bgsave

save 900 1: 每隔900s(15min),如果有超過1個key發生了變化,就寫一份新的 RDB 檔案。

save 300 10:每隔300s(5min),如果有超過10個key發生了變化,就寫一份新的RDB檔案。

save 60 10000:每隔60(1min),如果有超過10000個key發生了變化,就寫一份新的RDB檔案。

image-20231113224904050

Redis 6.2以及Redis7:

image-20231113225002784

操作步驟

自動備份:

Redis7版本,按照redis.conf 裡配置的 save < seconds > < changes >

image-20231116204828899

本次案例5秒2次修改

image-20231116204911597

修改dump檔案儲存路徑

預設:image-20231116205025557

自定義修改的路徑 image-20231116205125462

且可以進入redis裡用CONFIG GET dir 獲取目錄 image-20231116205324497

修改dump檔名稱 image-20231116205455282

 

觸發備份

第一種情況:

image-20231116215303787

第二種情況:

image-20231116215428284

如何恢復

將備份檔案(dump.rdb)移動到 redis 安裝目錄並啟動服務即可。

備份成功後故意用flushdb清空redis,看下是否可以恢復資料。

結論:執行flushall、flushdb、shutdown命令都會產生dump.rdb檔案,但裡面是空的,無意義。

物理恢復,一定要服務和備份 分級隔離

(不可以把備份檔案dump.rdb和生產redis伺服器放在同一臺機器,必須分開各自儲存,以防生產機物理損壞後備份檔案也掛了)

手動備份

Redis提供了兩個命令來生成RDB檔案,分別是 savebgsave

  • save:在主程式中執行 會阻塞 當前Redis伺服器,直到持久化工作完成,執行save命令期間,Redis不能處理其他命令,線上禁止使用(試試就逝世)

image-20231116223711588

image-20231116223723803

  • bgsave(預設):Redis會在後臺非同步進行快照操作,不阻塞 ,快照同時還可以響應客戶端請求,該觸發方式會fork一個子程式由子程式複製持久化過程。

image-20231116223820542

image-20231116223840043

Redis會使用bgsave對當前記憶體中的所有資料做快照,這個操作是子程式在後臺完成的,這就允許主程式同時可以修改資料。

什麼是fork?

image-20231116224133491

在Linux程式中,fork()會產生一個和父程式完全相同的子程式,但子程式在此後多會exec系統呼叫,出於效率考慮,儘量避免膨脹。

  • 可以透過LASTSAVE命令獲得最後一次成功執行快照的時間

    image-20231116224541272image-20231116224648981

 

優劣總結:

優勢:

官網說明:

image-20231116225536415

翻譯:

image-20231116225544803

小總結:

  • 適合大規模的資料恢復

  • 按照業務定時備份

  • 對資料完整性和一致性要求不高

  • RDB檔案在記憶體中的載入速度要比AOF快得多

劣勢:

官網說明:

image-20231116225822437

image-20231116225831677

小總結:

  • 在一定間隔時間做一次備份,如果Redis意外down掉的話,就會丟失從當前至最近一次快照期間的資料。

  • 記憶體資料的全量同步,如果資料量太大會導致I/O嚴重影響伺服器效能。

  • RDB依賴於主程式的fork,在更大的資料集中,這可能會導致服務請求的瞬間延遲。

  • fork的時候記憶體中的資料被克隆了一份,幾乎2倍的膨脹性,需要考慮

 

資料丟失案例:

錄入資料:

image-20231116230224056

kill掉程式:

image-20231116230238580

Redis重啟恢復,檢視資料是否丟失:

image-20231116230316576

 

如何檢查修復dump.rdb檔案

image-20231117232447496

哪些情況會觸發RDB快照

  1. 配置檔案中預設的快照配置

  2. 手動save/bgsave命令

  3. 執行flushall/flushdb命令也會產生dump.rdb檔案,但裡面是空的,沒意義

  4. 執行shutdown且沒有設定開啟AOF持久化

  5. 主從複製時,主節點自動觸發

如何禁用快照

  • 動態停止所有RDB儲存規則的方法(命令列):redis-cli config set save ""

  • 配置檔案 image-20231117232804521

     

RDB最佳化配置項詳解

配置檔案SNAPSHOTTING模組

  • save < seconds > < changes > 多少秒內發生多少次改變進行備份

  • dbfilename 自定義dump檔案的名稱

  • dir 自定義dump檔案儲存位置

  • stop-writes-on-bgsave-error

image-20231117233554489

預設yes;如果配置成no,表示你不在乎資料不一致或者有其他的手段發現和控制這種不一致,那麼在快照寫入失敗時,也能確保redis繼續接受新的寫請求

 

  • rdbcompression

image-20231117233733011

預設yes,對於儲存到磁碟中的快照,可以設定是否進行壓縮儲存。如果是的話,redis會採用LZF演算法進行壓縮。 如果你不想消耗CPU來進行壓縮的話,可以設定為關閉此功能

 

  • rdbchecksum

    image-20231117233909863

預設yes,在儲存快照後,還可以讓redis使用CRC64演算法來進行資料校驗,但是這樣做會增加大約10%的效能消耗,如果希望獲取到最大的效能提升,可以關閉此功能

 

  • rdb-del-sync-files

    image-20231117234015070

rdb-del-sync-files:在沒有永續性的情況下刪除複製中使用的RDB檔案啟用。預設情況下no,此選項是禁用的。

 

image-20231117234129916

 

AOF持久化

以日誌的形式記錄每個寫操作,將Redis執行過的所有寫指令記錄下來(讀指令不記錄),只許追加檔案但不可改寫檔案,Redis啟動之初會讀取該檔案重新構建資料,換言之,Redis重啟的話就根據日誌檔案的內容將寫指令從前到後執行一次以完成資料的恢復工作。

預設情況下,Redis是沒有開啟AOF(append only file)的。開啟AOF功能需要設定配置:appendonly yes

AOF儲存的是 appendonly.aof 檔案

AOF持久化工作流程

image-20231118115840064

  1. Client作為命令的來源,會有多個源頭以及源源不斷的請求命令。

  2. 在這些命令到達 Redis Server 以後並不是直接寫入AOF檔案,會將這些命令先放入 AOF快取 中進行儲存。這裡的AOF緩衝區實際上是記憶體中的一片區域,存在的目的是當這些命令達到一定量以後再寫入磁碟,避免頻繁的磁碟IO操作。

  3. AOF緩衝會根據AOF緩衝區同步檔案的 三種寫回策略 將命令寫入磁碟上的AOF檔案。

  4. 隨著寫入AOF內容的增加為避免膨脹,會根據規則進行命令的合併(又稱AOF重寫、AOF rewrite、AOFRW),從而起到AOF檔案壓縮的目的。

  5. 當Redis Server 伺服器重啟的時候會從AOF檔案載入資料。

AOF緩衝區三種寫回策略

  • Always:同步寫回,每個寫命令執行完立刻同步的將日誌寫回磁碟

  • Everysec:每秒寫回,每個寫命令執行完,只是先把日誌寫到AOF檔案的記憶體緩衝區,每隔1秒把緩衝區中的內容寫入磁碟

  • no:作業系統控制的寫回,每個寫命令執行完,只是先把日誌寫到AOF檔案的記憶體緩衝區,由作業系統決定何時將緩衝區內容寫回磁碟

    總結:

    配置項寫回時機優點缺點
    Always 同步寫回 可靠性高,資料基本不丟失 每個寫命令都要落盤,效能影響較大
    Everysec 每秒寫回 效能適中 當機時丟失1秒內的資料
    No 作業系統控制的寫回 效能好 當機時丟失資料較多

     

配置檔案

開啟AOF

image-20231119093614681

使用預設寫回策略,每秒鐘 image-20231119100209908
AOF檔案儲存路徑

Redis 6:

AOF儲存檔案的位置和RDB儲存檔案的位置一樣,都是透過redis.conf 配置檔案的 dir 配置

Redis 7:

自定義一個appenddirname屬性,如圖配置AOF檔案儲存路徑是(dir/appenddirname):/myredis/appendonlydir/XXXX.aof

image-20231119100702290

AOF檔案儲存名稱

Redis 6:有且只有一個

image-20231119103604110

Redis 7:Multi Part AOF的設計

 

image-20231119104716589

image-20231119104726894

為什麼要設計MP-AOF?

為了解決AOFRW存在的問題(記憶體、CPU、磁碟IO開銷太大,程式碼複雜度較高)。

詳情可參考:Redis 7.0 Multi Part AOF的設計和實現-阿里雲開發者社群 (aliyun.com)

 

恢復

  1. 前提:修改預設的appendonly no 改為yes

  2. 寫操作,生成AOF檔案到指定的目錄

image-20231119123739506

  1. 正常恢復

    1. 重啟Redis然後重新載入,結果OK

    2. 寫入資料進Redis,備份aof檔案,然後flushdb+shutdown伺服器(新生成了dump和aof)

    3. 刪除dump和aof再看恢復

      image-20231119124143263

    4. 重啟Redis伺服器重新載入看看

      image-20231119124314075

      5. 停止伺服器,拿出我們的備份檔案修改後再啟動伺服器看看

    image-20231119124435161

    image-20231119124450679

    1. 異常恢復

      1.故意亂寫正常的AOF檔案,模擬網路閃斷檔案寫入error【vim /myredis/appendonlydir/appendonly.aof.1.incr.aof】

      image-20231119124725187

      1. 嘗試重啟Redis,發現啟動不了,是因為Redis啟動之後就會進入AOF檔案的載入

      image-20231119124944708

      1. 異常修復命令:redis-check-aof --fix

        image-20231119125307672

        image-20231119125330500

                4. 重啟OK

      image-20231119125544800

優劣勢

優勢:更好的保護資料不丟失、效能高、可做緊急恢復

image-20231119130512688image-20231119130521953

劣勢:相同資料集的資料而言AOF檔案要遠大於RDB檔案,恢復速度也慢於RDB檔案

AOF執行效率要慢於RDB,每秒同步策略較好,但不同步效率和RDB相同

image-20231119130720138image-20231119130728652

 

AOF重寫機制

由於AOF持久化是Redis不斷將寫命令記錄到 AOF 檔案中,隨著Redis不斷的進行,AOF 的檔案會越來越大,檔案越大,佔用伺服器記憶體越大以及 AOF 恢復要求時間越長。

為了解決這個問題,Redis新增了重寫機制,當AOF檔案的大小超過所設定的峰值時,Redis就會自動啟動AOF檔案的內容壓縮,只保留可以恢復資料的最小指令集

或者

可以手動使用命令 bgrewriteaof 來重新。

image-20231125093812898

注意:是且的關係(同時滿足2個條件)才會觸發。

  1. 根據上次重寫後的AOF大小,判斷當前AOF大小是不是增長了一倍(100%)

  2. 重寫時檔案大小滿足條件(64mb)

啟動AOF檔案的內容壓縮,只保留可以恢復資料的最小指令集。

舉個例子:比如有個key

一開始你 set k1 v1

然後改成 set k1 v2

最後改成 set k1 v3

如果不重寫,那麼這3條語句都在aof檔案中,內容佔空間不說啟動的時候都要執行一遍,共計3條命令;

但是,我們實際效果只需要set k1 v3這一條,所以,

開啟重寫後,只需要儲存set k1 v3就可以了只需要保留最後一次修改值,相當於給aof檔案瘦身減肥,效能更好。

AOF重寫不僅降低了檔案的佔用空間,同時更小的AOF也可以更快地被Redis載入。

 

案例:

配置準備:

開啟AOF image-20231125095657900

重寫峰值改為1k image-20231125095726153

關閉混合模式 image-20231125095800882

刪除之前的全部AOF和rdb,清除干擾項

 

自動觸發案例:

image-20231125101014592

重寫觸發:

image-20231125100711600

 

手動觸發案例:

客戶端向伺服器傳送bgrewriteaof命令

image-20231125101448816 image-20231125101523018

 

結論:

AOF檔案重寫並不是對原檔案進行重新整理,而是直接讀取伺服器現有的鍵值對,然後用一條命令去代替之前記錄這個鍵值對的多條命令,生成一個新的檔案後去替換原來的AOF檔案。

AOF檔案重寫觸發機制:透過redis.conf 配置檔案中的auto-aof-rewrite-percentage:100,以及auto-aof-rewrite-min-size:64mb 配置,也就是說預設Redis檔案惠濟路上次重寫的AOF大小,預設配置是當AOF檔案大小事上次rewrite後大小的一倍且檔案大於64mb時觸發

 

重寫原理:

1:在重寫開始前,redis會建立一個“重寫子程式”,這個子程式會讀取現有的AOF檔案,並將其包含的指令進行分析壓縮並寫入到一個臨時檔案中。

2:與此同時,主程式會將新接收到的寫指令一邊累積到記憶體緩衝區中,一邊繼續寫入到原有的AOF檔案中,這樣做是保證原有的AOF檔案的可用性,避免在重寫過程中出現意外。

3:當“重寫子程式”完成重寫工作後,它會給父程式發一個訊號,父程式收到訊號後就會將記憶體中快取的寫指令追加到新AOF檔案中

4:當追加結束後,redis就會用新AOF檔案來代替舊AOF檔案,之後再有新的寫指令,就都會追加到新的AOF檔案中

5:重寫aof檔案的操作,並沒有讀取舊的aof檔案,而是將整個記憶體中的資料庫內容用命令的方式重寫了一個新的aof檔案,這點和快照有點類似

 

AOF最佳化配置項

image-20231125102449691

小總結:

image-20231125102544546

RDB-AOF混合持久化

官網說明

image-20231125103252661

配置檔案說明

image-20231125103355368

資料恢復順序和載入流程

在同時開啟RDB和AOF持久化時,重啟時只會載入AOF檔案,不會載入RDB檔案

image-20231125103532732

二者區別

RDB持久化方式能夠在指定的時間間隔對你的資料進行快照儲存

AOF持久化方式記錄每次對伺服器寫的操作,當伺服器重啟的時候會重新執行這些命令來回復原始的資料,AOF命令以Redis協議追加儲存每次寫的操作到檔案末尾

同時開啟兩種持久化方式

在這種情況下,當Redis重啟的時候會優先載入AOF檔案來恢復原始的資料,因為在通常情況下,AOF檔案儲存的資料集要比RDB檔案儲存的資料集要完整。

RDB的資料不實時,同時使用兩者時伺服器重啟也只會找AOF檔案。那要不要只使用AOF呢?作者建議不要,因為RDB更適合用於備份資料庫(AOF在不斷變化不好備份),留著RDB作為一個萬一的手段。

推薦方式:RDB+AOF混合方式

結合了RDB和AOF的優點,技能快速載入又能避免丟失過多的資料。

開啟方式:

設定 aof-use-rdb-preamble yes 表示開啟,設為no表示禁用。

結論:RDB映象做全量持久化,AOF做增量持久化

先使用RDB進行快照儲存,然後使用AOF持久化記錄所有寫操作,當重寫策略滿足或手動觸發重寫的時候,將最新的資料儲存為新的RDB記錄。這樣的話,重啟服務的時候會從RDB和AOF兩部分恢復資料,既保證了資料完整性,又提高了恢復資料的效能。簡單來說:混合持久化方式產生的檔案一部分是RDB格式,一部分是AOF格式。AOF包括了RDB頭部+AOF混寫。

image-20231125105236948

純快取模式

同時關閉RDB+AOF

save "" :禁用rdb,禁用rdb持久化模式下,我們仍然可以使用save、bgsave命令生成rdb檔案

appendonly no:禁用AOF,但我們仍然可以使用bgrewriteaof命令生成AOF檔案