Redis的三種持久化策略及選取建議

来源:https://www.cnblogs.com/reim/archive/2023/05/15/17387751.html
-Advertisement-
Play Games

在探究 Kafka 核心知識之前,我們先思考一個問題:什麼場景會促使我們使用 Kafka? 說到這裡,我們頭腦中或多或少會蹦出非同步解耦和削峰填谷等字樣,是的,這就是 Kafka 最重要的落地場景。 ...


概述

Redis是一個基於記憶體的高性能的鍵值型資料庫,它支持三種不同的持久化策略:RDB(快照)、AOF(追加文件)、混合。這三種策略各有優缺點,需要根據不同的場景和需求進行選擇和配置。本文將介紹這三種策略

RDB(快照)

概述

RDB持久化策略是指在一定的時間間隔內,將Redis記憶體中的數據以二進位文件的形式保存到硬碟上。這個二進位文件就是一個快照,它記錄了某個時刻Redis記憶體中的所有數據。RDB持久化策略可以通過配置文件或者命令來觸發,配置文件中可以設置多個條件,當任意一個條件滿足時,就會執行一次快照操作。如下所示:

save 900 1 # 900秒內執行一次 set 操作 則持久化1次
save 300 10 # 300秒內執行10次 set 操作,則持久化1次
save 60 10000 # 60秒內執行10000次 set 操作,則持久化1次

命令有兩種:

  • save:不建議使用,會阻塞redis服務的進程,直到成功創建RDB文件
  • bgsave:父進程創建一個子進程生成RDB文件,父進程可以正常處理客戶端的指令,不影響主進程的服務

優缺點

RDB持久化策略的優點有:

  • RDB文件是一個緊湊的二進位文件,占用空間小,傳輸速度快,適合做備份和災難恢復
  • RDB文件恢複數據的速度比AOF快,因為只需要載入一次文件即可
  • RDB持久化對Redis伺服器的性能影響較小,因為大部分工作由子進程完成

RDB持久化策略的缺點有:

  • RDB文件不能實時或者近實時地反映Redis記憶體中的數據,因為它是定時觸發的。如果在兩次快照之間發生故障,可能會丟失一部分數據
  • RDB文件在生成過程中可能會占用較多的記憶體和CPU資源,因為需要複製主進程的記憶體並執行壓縮操作

AOF(追加文件)

概述

AOF持久化策略是指將Redis伺服器執行的每一條寫命令都記錄到一個文本文件中,這個文本文件就是一個追加文件(append only file)

AOF有三種持久化策略,也就是刷盤策略。可以根據不同的場景使用不同的刷盤策略

然而隨著時間的推移,AOF文件也會越來越大,因為它記錄了所有的寫命令。這樣會導致AOF文件占用過多的磁碟空間,以及恢複數據的時間過長。為瞭解決這個問題,Redis提供了AOF重寫機制,來壓縮和優化AOF文件。

優缺點

AOF持久化策略的優點有:

  • AOF文件可以實時或者近實時地記錄Redis記憶體中的數據,因為它是每次寫命令或者每秒鐘同步一次。如果在同步之間發生故障,可能會丟失一部分數據,但是數據丟失的概率比RDB小。
  • AOF文件是一個文本文件,可以方便地查看和編輯。AOF文件中的命令是Redis協議格式的,可以直接用Redis客戶端來執行。
  • AOF文件可以自動進行重寫,以減少冗餘命令和文件體積。重寫過程不影響Redis伺服器的正常服務,也不會丟失任何數據。

AOF持久化策略的缺點有:

  • AOF文件通常比RDB文件大,占用更多的磁碟空間
  • AOF文件恢複數據的速度比RDB慢,因為需要重新執行所有的命令
  • AOF文件在寫入過程中可能會出現數據不一致的情況,例如命令只寫入了一半或者寫入了錯誤的命令。這種情況下需要用redis-check-aof工具來修複AOF文件

AOF刷盤策略

當Redis重啟時,可以通過重新執行追加文件中的命令來恢複數據。AOF持久化策略可以通過配置文件來開啟和設置,它決定了寫命令記錄到AOF文件的頻率。有三個選項:

  • no:寫入緩存,什麼時候刷盤由redis決定
  • everysec:每隔一秒刷一次盤
  • always:寫入緩存時同時寫入磁碟(儘快刷盤,而不是實時刷盤)

以下是三個策略的對比:

類型 數據安全性 性能
no
everysec 較高 較高
always

AOF重寫

AOF重寫機制的原理是:Redis會創建一個新的AOF文件,然後根據記憶體中的當前數據狀態,生成相應的寫命令,並寫入到新的AOF文件中。這樣新的AOF文件就只包含了最終數據的寫命令,而不包含任何無效或者冗餘的命令。例如:

# 原始AOF文件
set a 1
set b 2
incr a
del b
set c 3

# 重寫後的AOF文件
set a 2
set c 3

上圖就是重寫前和重寫後的文件對比,因為AOF是追加的,是順序讀寫(ES也是這樣的),所以重寫後的命令set a 1incr a變成為set a 2。為了保證在AOF重寫期間的新數據不丟失,Redis中引入了AOF重寫緩衝區。當開始執行AOF文件重寫之後又接收到客戶端的請求命令,不但要將命令寫入原本的AOF緩衝區(根據上面提到的參數刷盤),還要同時寫入AOF重寫緩衝區:

一旦子進程完成了AOF文件的重寫,此時會向父進程發出信號,父進程收到信號之後會進行阻塞(阻塞期間不執行任何命令),併進行以下兩項工作:

  • AOF重寫緩衝區的文件刷新到新的AOF文件內
  • 將新AOF文件進行改名並原子操作的替換掉舊的AOF文件

隨後,在完成了上面的兩項工作之後,整個AOF重寫工作完成,父進程開始正常接收命令。

  • 自動觸發:自動觸發可以通過以下參數進行設置。
# 文件大小超過上次AOF重寫之後的文件的百分比。預設100
# 也就是預設達到上一次AOF重寫文件的2倍之後會再次觸發AOF重寫
auto-aof-rewrite-percentage 100
# 設置允許重寫的最小AOF文件大小,預設是64M
# 主要是避免滿足了上面的百分比,但是文件還是很小的情況。
auto-aof-rewrite-min-size 64mb
  • 手動觸發:執行bgrewriteaof命令。

選取正確的持久化策略

Redis現有的持久化策略有三種:

  • AOF
  • RDB
  • AOF與RDB混合

他們各有優缺點,需要結合不同的應用場景綜合考慮,首先先講解AOFRDB的選擇,再講解混合模式

AOF和RDB的選擇

在Redis中,AOF和RDB兩種持久化方式各有優缺點,一般來說,有以下幾個方面需要參考:

  • 數據安全性:如果要求數據不丟失,推薦AOF
    • AOF可以採取每秒同步一次數據或每次寫操作都同步用來保證數據安全性
      • 如果使用每秒同步一次策略,則最多丟失一秒的數據
      • 如果使用每次寫操作都同步策略,安全性達到了極致,但這會影響性能
    • RDB是一個全量的二進位文件,恢復時只需要載入到記憶體即可,但是可能會丟失最近幾分鐘的數據(取決於RDB持久化策略)
  • 數據恢復速度:如果要求快速恢複數據,推薦RDB
    • AOF需要重新執行所有的寫命令,恢復時間會更長
    • RDB是一個全量的二進位文件,恢復時只需要載入到記憶體即可
  • 數據備份和遷移:如果要求方便地進行數據備份和遷移,推薦RDB
    • AOF文件可能會很大,傳輸速度慢
    • RDB文件是一個緊湊的二進位文件,占用空間小,傳輸速度快
  • 數據可讀性:如果要求能夠方便地查看和修改數據,推薦AOF
    • AOF是一個可讀的文本文件,記錄了所有的寫命令,可以用於災難恢復或者數據分析
    • RDB是一個二進位文件,不易查看和修改
數據安全性 數據恢復速度 數據備份和遷移 數據可讀性
AOF
RDB

AOF與RDB的混合模式

綜合上一節,我們可以根據不同的場景和需求來選擇合適的持久化方式。但是,在實際應用中,並不一定要二選一,也可以同時使用AOF和RDB兩種持久化方式。這樣可以利用AOF來保證數據不丟失,作為數據恢復的第一選擇;用RDB做不同程度的冷備份,當AOF備份文件丟失或損壞不可用時,可以使用RDB快照文件快速地恢複數據

綜上所述,混合模式兼併了RDB重啟後的快速恢復能力和AOF丟失數據風險低的能力,具體操作流程如下:

  1. 子進程會通過BGSAVE 寫入AOF中
  2. 觸發BGREWRITEAOF後,會將AOF寫入到文件
  3. 將含有RDB和AOF的數據覆蓋舊的AOF文件(這時AOF文件一半為RDB,一半為AOF)

混合模式的AOF文件:

REDIS0008?redis-ver4.0.1?redis-bits繞?ctime聮~`?used-mem?? ?aof-preamble??repl-id(6c3378899b63bc4ebeaafaa09c27902d514eeb1f?repl-offset??? list1?77   /   appleorangegrape?e k1v1彞髖S[zb*2
$6
SELECT
$1
0
*3
$4
sadd
$8
gamedisk
$4
nioh
*3
$4
sadd
$8
gamedisk
$4
tomb

如果想要開啟混合模式,在redis.conf中配置:

aof-use-rdb-preamble yes

同時使用AOF和RDB兩種持久化方式也需要註意一些問題:

  • AOF重寫和RDB持久化可能會同時發生衝突,導致記憶體、CPU和磁碟的消耗增加。為瞭解決這個問題,Redis採用了一些策略來協調兩者之間的關係。具體可以參考下麵的介紹(AOF重寫和RDB持久化的衝突
  • AOF文件可能會變得很大,導致磁碟空間不足或者恢復時間過長。為瞭解決這個問題,Redis提供了AOF重寫機制來壓縮AOF文件。具體可以參考上一節(AOF重寫
  • AOF文件可能會被損壞或者丟失,導致數據無法恢復。為瞭解決這個問題,Redis提供了AOF校驗機制來檢測AOF文件是否完整。具體可以參考下麵的介紹(AOF校驗機制

AOF重寫和RDB持久化的衝突

在Redis中,AOF重寫和RDB持久化可能會同時發生,這會導致一些衝突和問題。例如:

  • AOF重寫和RDB持久化都需要fork子進程,如果兩個子進程同時存在,會增加記憶體的消耗和系統的負載。
  • AOF重寫和RDB持久化都需要寫入磁碟,如果兩個文件同時寫入,會增加磁碟的壓力和IO的開銷。
  • AOF重寫和RDB持久化都需要在完成後通知主進程,如果兩個信號同時到達,可能會造成信號丟失或者處理錯誤。

為瞭解決這些衝突和問題,Redis採用了以下策略:

  • 如果AOF重寫和RDB持久化同時被觸發,那麼只有一個子進程會被創建,優先執行RDB持久化,然後再執行AOF重寫。這樣可以避免同時存在兩個子進程的情況。
  • 如果AOF重寫正在進行,而此時又收到了RDB持久化的請求,那麼RDB持久化會被延遲到AOF重寫完成後再執行。這樣可以避免同時寫入兩個文件的情況。
  • 如果AOF重寫和RDB持久化都完成了,那麼主進程會先處理RDB持久化的信號,然後再處理AOF重寫的信號。這樣可以避免信號丟失或者處理錯誤的情況。

總之,Redis通過優先順序、延遲和順序等方式來協調AOF重寫和RDB持久化的衝突和問題,保證了數據的完整性和一致性,下圖為簡要說明。

場景 策略
AOF重寫與RDB持久化同時被觸發 優先RDB
AOF重寫正在進行 優先AOF
AOF重寫和RDB持久化都完成 優先RDB

AOF校驗機制

AOF校驗機制是指在Redis啟動時,對AOF文件進行檢查,判斷文件是否完整,是否有損壞或者丟失的數據。如果發現AOF文件有問題,Redis會拒絕啟動,並給出相應的錯誤信息

AOF校驗機制的原理是使用一個64位的校驗和(checksum)來對AOF文件進行驗證。校驗和是一個數字,它是根據AOF文件的內容計算出來的,如果AOF文件的內容發生了任何改變,那麼校驗和也會發生變化。因此,通過比較計算出來的校驗和和保存在AOF文件末尾的校驗和,就可以判斷AOF文件是否完整。

具體來說,AOF校驗機制的過程如下:

  • 當Redis執行AOF重寫時,它會在新的AOF文件末尾寫入一個特殊的命令:*1\r\n$6\r\nCHECKSUM\r\n,這個命令表示接下來要寫入一個校驗和
  • Redis會使用CRC64演算法,對新的AOF文件中除了最後一行之外的所有內容進行計算,得到一個64位的數字作為校驗和,並將這個數字以16進位的形式寫入到新的AOF文件末尾。
  • Redis會將新的AOF文件替換舊的AOF文件,並將校驗和保存在記憶體中
  • 當Redis重啟時,它會讀取AOF文件,並使用同樣的CRC64演算法,對除了最後一行之外的所有內容進行計算,得到一個64位的數字作為校驗和,並將這個數字與記憶體中保存的校驗和進行比較
  • 如果兩個校驗和相同,說明AOF文件沒有損壞或者丟失數據,Redis會繼續啟動並載入AOF文件中的數據
  • 如果兩個校驗和不同,說明AOF文件有問題,Redis會拒絕啟動,並給出類似於Bad file format reading the append only file: checksum mismatch這樣的錯誤信息

通過這種方式,Redis可以保證在啟動時檢測到AOF文件是否完整,從而避免載入錯誤或者不完整的數據。當然,這種機制也有一些局限性:

  • AOF校驗機制只能在Redis啟動時執行,如果在運行過程中AOF文件被修改或者損壞,Redis無法及時發現
  • AOF校驗機制只能檢測到AOF文件是否完整,但不能檢測到AOF文件是否正確。比如說,如果有人惡意地修改了AOF文件中的某些命令或者參數,導致數據邏輯上出現錯誤,那麼Redis無法識別出這種情況。
  • AOF校驗機制會增加Redis啟動時的時間開銷,因為需要對整個AOF文件進行計算。如果AOF文件很大,那麼這個過程可能會很慢。

總之,AOF校驗機制是一種簡單而有效的方法,可以保證在Redis啟動時檢測到AOF文件是否完整。但是它也有一些局限性和代價,需要在實際應用中權衡利弊。

三種模式的選擇建議

具體的選擇建議如下:

  • 如果對數據完整性要求不高,可以只使用RDB,或者將AOF的同步頻率設置為每秒一次
  • 如果想讓數據儘可能不丟失,可以只使用AOF,並將AOF的同步頻率設置為每次寫入操作都同步
  • 如果對數據完整性和性能都有要求,可以同時使用AOF和RDB,並將AOF的同步頻率設置為每秒一次。這樣既可以保證數據的安全性,又可以利用RDB進行快速的數據恢復
  • 如果既想節省磁碟空間,又想提高數據恢復速度,可以只使用RDB,並適當調整RDB的快照頻率

這三種模式各有優缺點,需要根據具體的場景和需求來進行選擇和配置。在選擇時,需要考慮以下幾個因素:

  • 數據完整性:即數據丟失的風險和可接受的範圍
  • 數據恢復速度:即從持久化文件恢復到記憶體中所需的時間
  • 磁碟空間占用:即持久化文件所占用的磁碟空間大小
  • 寫入性能:即持久化操作對Redis服務端的寫入性能的影響

註意:
AOF策略設置為 always 或 everysec,並且BGSAVE BGREWRITEAOF正在對磁碟執行大量 I/O 時,Redis 刷盤可能會阻塞
可以設置no-appendfsync-on-rewrite yes,來緩解這個問題。這樣的話,當另一個子進程正在保存的時候,Redis 的持久性與appendfsync no相同。實際上,最嚴重的情況是丟失30秒的日誌

持久化策略常見問題及解決方案

AOF文件過大

當AOF文件過大時,會占用磁碟空間,影響寫入性能,甚至導致Redis啟動失敗。可以使用bgrewriteaof命令或者配置auto-aof-rewrite-percentageauto-aof-rewrite-min-size參數來觸發AOF重寫操作,將AOF文件壓縮為最小的命令集合

# 文件大小超過上次AOF重寫之後的文件的百分比。預設100
# 也就是預設達到上一次AOF重寫文件的2倍之後會再次觸發AOF重寫
auto-aof-rewrite-percentage 100
# 設置允許重寫的最小AOF文件大小,預設是64M
# 主要是避免滿足了上面的百分比,但是文件還是很小的情況。
auto-aof-rewrite-min-size 64mb

AOF文件損壞

當AOF文件損壞時,會導致Redis無法正常啟動或者恢複數據。可以使用redis-check-aof工具來修複AOF文件,或者使用備份的RDB文件來恢複數據

AOF 文件可能會被截斷

在 Redis 啟動過程中,當 AOF 數據被載入回記憶體時,可能會發現 AOF 文件在最後被截斷

  • aof-load-truncated yes,則載入截斷的 AOF 文件,並且記錄日誌
  • aof-load-truncated no,則伺服器會因錯誤拒絕啟動,且需要在啟動伺服器之前使用redis-check-aof修複aof文件

可以在redis.conf中配置:

aof-load-truncated yes

可記錄時間戳幫助恢複數據

如果在AOF記錄時間戳,可能會與現有的AOF解析器不相容,預設關閉

redis.conf中配置:

aof-timestamp-enabled no

RDB文件丟失

當RDB文件丟失時,會導致Redis無法恢複數據。為瞭解決這個問題,可以使用備份的AOF文件或者其他節點的RDB文件來恢複數據,或者增加RDB的快照頻率來減少數據丟失的風險

RDB文件損壞

當RDB文件損壞時,會導致Redis無法恢複數據。為瞭解決這個問題,可以使用redis-check-rdb工具來檢查和修複RDB文件,或者使用備份的AOF文件或者其他節點的RDB文件來恢複數據


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 前言 今天我們來分享一款非常有趣的登錄界面,它使用HTML和CSS製作,具有動態的水波紋效果,讓用戶在登錄時感受到了一股清涼之感。 基本html框架 <!DOCTYPE html> <html lang="en"> <head> <met ...
  • 前言 一旦給 axios 添加了攔截器,就會對所有的 post、get 等請求進行攔截。但不是所有的請求都需要進行攔截,如公共的請求,即不需要用戶登錄即可發起請求的 api 我們應當放行。 通過 axios.interceptors.request.eject(requestId) 清除 reque ...
  • 前言 公司展示大屏需要寫滾動表格,通過滾動播放數據,自己隨便摸了一個基於動畫的自動滾動表格 原理 根據每行的大小和設置的每行滾動時間設置滾動位置,動態添加動畫,並把數組第一項移動到最後一項,並訂閱該動畫結束的事件,在結束時迴圈執行該操作。 其他功能 可自定義單元格或行 可設置中文映射和取消顯示 單元 ...
  • Tips: 字元串方法match()返回根據正則表達式匹配到的結果 1. 常用符號/鏈接標誌 1.1 開頭結尾標誌 ^ 以...開頭 $以...結尾 const reg1 = /^\d/ // 以數字開頭 const reg2 = /^[a-z]/ // 以小寫字母開頭 const reg3 = / ...
  • 在JavaScript中,純函數是指在相同的輸入下,始終產生相同的輸出,並且沒有副作用的函數。純函數不會修改或依賴於函數之外的狀態,也不會對外部環境產生任何可觀察的影響。 以下是純函數的特點: 1. 確定性 :對於相同的輸入,純函數總是產生相同的輸出。這意味著,如果你用相同的參數多次調用純函數,它將 ...
  • 函數式編程是一種編程範式,它將程式抽象為函數和數據結構,通過函數調用來實現程式的功能,並且函數可以作為參數傳遞給其他函數。 ...
  • 2023-05-15 (1)js中的同步任務與非同步任務 ①同步任務是指:不耗時的任務,就是執行很快, ②非同步任務是指:耗時的任務,它裡面有一個機制是EventLoop(事件迴圈),即值耗時任務會被js分配到宿主環境中進行執行,執行後的結果放到一個“消息隊列”中,當js將同步任務執行完畢後,才會調用異 ...
  • 本文將給大家介紹一種簡潔明瞭軟體架構可視化模型——C4模型,並手把手教大家如何使用代碼繪製出精美的C4架構圖。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...