你說你精通Redis,你看過持久化的配置嗎?

ITPUB社群發表於2022-11-21

今天讓我們從理論和配置兩個層面來揭開Redis持久化的神秘面紗。

所謂持久化可以簡單理解為將記憶體中的資料儲存到硬碟上儲存的過程。持久化之後的資料在系統重啟或者當機之後依然可以進行訪問,保證了資料的安全性。

Redis有兩種持久化方案,一種是快照方式(SNAPSHOTTING),簡稱RDB;一種是隻追加模式(APPEND ONLY MODE),稱為AOF。接下來讓我們分別瞭解一下它們的使用與注意事項。

RDB

RDBRedis DataBase的縮寫,是 Redis 預設的持久化方案。它能夠在指定的時間間隔內將記憶體資料集快照(snapshot)寫入磁碟,恢復時將快照檔案( dump.rdb )讀回記憶體。

你說你精通Redis,你看過持久化的配置嗎?

我們先來扒一下配置檔案中的SNAPSHOTTING:

配置檔案

save  <seconds> <changes>

在給定的秒數內,如果對資料庫執行的寫入運算元達到設定的值,則將資料同步到資料檔案。支援多個條件配合,Redis預設配置檔案中提供了三個條件:

save 900 1 //900s內有1個更改
save 300 10 //300s內有10個更改
save 60 10000 //60s內有10000次更改

注意:若不想用RDB方案,可以把 save ""的註釋開啟,上邊三個註釋掉。

stop-writes-on-bgsave-error yes

bgsave出現錯誤時,Redis是否停止執行寫命令;

  • 如果為yes,則當硬碟出現問題時,Redis將停止接受寫入操作,這樣我們可以及時發現,避免資料的大量丟失;
  • 如果為no,則Redis無視bgsave的錯誤繼續執行寫命令。

如果已經設定了對Redis伺服器的正確監視和永續性,即採用了其他手段發現和控制資料完整性,可能希望禁用此功能,以便即使在磁碟、許可權等方面出現問題時,Redis仍能正常工作。

注意:如果後臺儲存過程將再次開始工作,Redis將自動允許再次寫入。

rdbcompression yes

指定儲存到本地資料庫時是否壓縮Redis採用LZF壓縮)資料,預設為yes。如果為了節省CPU時間,可以關閉該選項,但會導致資料庫檔案變得巨大。

rdbchecksum yes

RDB版本5開始,在儲存快照後,還可以使用CRC64演算法來進行資料校驗,CRC64校驗放在檔案的末尾。開啟之後,儲存和載入RDB檔案時會增加大約10%的效能消耗,如果希望獲取到最大的效能提升,可以關閉此功能。

禁用校驗和建立的RDB檔案的校驗和為零,這將告訴載入程式碼跳過檢查。

dbfilename dump.rdb

指定本地資料庫檔名,重啟之後自動載入進記憶體,手動執行save 命令的話即刻生效。

大坑請注意flushallshutdown命令都會清空並提交至dump.rdb

dir ./

指定本地資料庫存放目錄。

理論

工作方式

  • Redis 需要儲存dump.rdb檔案時,它會呼叫系統函式fork(),建立一個子程式(與主程式完全一致);
  • 子程式將資料集寫入臨時檔案RDB中;
  • 當子程式完成對新 RDB 檔案的寫入時,Redis 用新 RDB 檔案替換原來的 RDB 檔案,並刪除舊的 RDB 檔案。

這種工作方式使得 Redis 可以從寫時複製(copy-on-write)機制中獲益。

如何觸發RDB快照

  1. 配置檔案中預設的快照配置;
  2. 命令save(阻塞, 只管儲存快照,其他的等待)或者是bgsave(非同步)命令,快照同時還可以響應客戶端命令;
  3. 執行flushall 命令,清空資料庫所有資料,意義不大;
  4. 執行shutdown 命令,保證伺服器正常關閉且不丟失任何資料,意義也不大。

透過RDB檔案恢復資料

在實際開發中,一般會考慮到物理機硬碟損壞的情況,所以我們會選擇備份dump.rdb檔案。將備份的dump.rdb 檔案複製到redis的安裝目錄的bin目錄下,重啟redis服務即可。

優點

  • RDB是一個非常緊湊的檔案,非常適用於資料集的備份;
  • RDB是一個緊湊的單一檔案,很方便傳送到另一個遠端資料中心或者亞馬遜的S3(可能加密),非常適用於災難恢復;
  • Redis的主程式不進行I/O操作,確保了極高的效能;
  • 適合大規模資料的恢復,對於資料的完整性和一致性要求不高的話,RDBAOF方式更加高效。

缺點

  • Redis意外當機時,你可能會丟失幾分鐘的資料;
  • RDB 需要經常fork子程式來儲存資料集到硬碟上,當資料集比較大的時候,fork的過程是非常耗時的,可能會導致Redis在一些毫秒級內不能響應客戶端的請求。如果資料集巨大並且CPU效能不是很好的情況下,這種情況會持續1秒;AOF也需要fork,但是可以調節重寫日誌檔案的頻率來提高資料集的耐久度。

AOF

為了解決RDB方式在當機時丟失資料過多的問題,從1.1 版本開始,Redis增加了一種durable的持久化方式:AOF

AOFAppend Only File的縮寫,預設不開啟。AOF以日誌的形式來記錄每個寫操作,只允許追加檔案但不可以改寫檔案,當伺服器重啟的時候會重新執行這些命令來恢復原始的資料。

我們再來看一下配置檔案中的APPEND ONLY MODE:

配置檔案

appendonly no

預設為關閉狀態,改為yes開啟持久化。AOFRDB可以同時啟用而不會出現問題。

appendfilename "appendonly.aof"

檔案預設名稱,啟動即建立。載入先於dump.rdb檔案

appendfsync

同步策略:系統函式fsync() 告訴作業系統在磁碟上實際寫入資料。Redis支援三種不同的模式

appendfsync always //每次發生資料變更會被立即記錄到磁碟,效能較差但資料完整性比較好
appendfsync everysec //預設推薦,非同步操作,每秒記錄,如果當機,有1秒內資料丟失
appendfsync no //不同步,只有在作業系統需要時在重新整理資料

要想了解接下來的配置內容,先得說一下“日誌重寫”的原理:

重寫

由於AOF採用的是將命令追加到檔案末尾的方式,所以隨著寫入命令的不斷增加,AOF檔案的體積會變得越來越大。為避免出現此種情況,新增了重寫機制:可以在不打斷服務客戶端的情況下,對AOF檔案進行重建(rebuild)。

重寫觸發: 透過執行bgrewriteaof命令,可以生成一個新的AOF檔案,該檔案包含重建當前資料集所需的最少命令。Redis 2.2需手動執行該命令,Redis 2.4則可以透過修改配置檔案的方式自動觸發(配置在下邊涉及)。

重寫原理:

  • Redis 執行系統函式fork() ,建立一個子程式(與主程式完全一致);
  • 子程式開始將新 AOF 檔案的內容寫入到臨時檔案;
  • 對於所有新執行的寫入命令,父程式一邊將它們累積到一個記憶體快取中,一邊將這些改動追加到現有 AOF 檔案的末尾,這樣即使在重寫的中途發生停機,現有的 AOF 檔案也是安全的;
  • 當子程式完成重寫工作時,它給父程式傳送一個訊號,父程式在接收到訊號之後,將記憶體快取中的所有資料追加到新 AOF 檔案的末尾。
  • Redis 原子地用新檔案替換舊檔案,之後所有命令都會直接追加到新 AOF檔案的末尾。

no-appendfsync-on-rewrite no

當我們同時執行主程式的寫操作和子程式的重寫操作時,兩者都會操作磁碟,而重寫往往會涉及到大量的磁碟操作,這樣就會造成主程式在寫aof檔案的時候出現阻塞的情形。

為了解決這個問題,no-appendfsync-on-rewrite引數出場了。

  • 如果該引數設定為no,是最安全的方式,不會丟失資料,但是要忍受阻塞的問題;
  • 如果設定為yes,這就相當於將appendfsync設定為no,這說明並沒有執行磁碟操作,只是寫入了緩衝區。因此這樣並不會造成阻塞(因為沒有競爭磁碟),但是如果這個時候redis掛掉,就會丟失資料。丟失多少資料呢?在linux的作業系統的預設設定下,最多會丟失30s的資料。

因此,如果應用系統無法忍受延遲,而可以容忍少量的資料丟失,則設定為yes;如果應用系統無法忍受資料丟失,則設定為no

auto-aof-rewrite-percentage 100

重寫百分比,預設為上次重寫後aof檔案大小的一倍。

auto-aof-rewrite-min-size 64mb

重寫觸發的最小值:64mb。

根據auto-aof-rewrite-min-sizeauto-aof-rewrite-percentage引數確定自動觸發時機。Redis會記錄上次重寫時的AOF大小,預設配置是當AOF檔案大小是上次rewrite後大小的一倍且檔案大於64M時觸發。

大型網際網路公司一般都是3G起步

aof-load-truncated yes

AOF檔案被截斷時,即AOF檔案的最後命令不完整,如果此時啟動Redis,會將AOF資料載入回記憶體,此時便會出現問題。

  • yes:載入一個截斷的AOFRedis伺服器開始發出日誌,通知使用者該事件;
  • no:伺服器將中止並出現錯誤,拒絕啟動。

當我們得知AOF檔案報錯時,可以用以下方法來修復出錯的 AOF 檔案:

  • 為現有的 AOF檔案建立一個備份;

  • 使用 Redis 附帶的 redis-check-aof 命令,對原來的AOF檔案進行修復;

    • redis-check-aof –fix

    • redis-check-aof --fix appendonly.aof  修復命令,殺光不符合規範的語法

  • 可選)使用 diff -u 對比修復後的 AOF檔案和原始 AOF 檔案的備份,檢視兩個檔案之間的不同之處;

  • 重啟 Redis伺服器,等待伺服器載入修復後的 AOF檔案,並進行資料恢復。

aof-use-rdb-preamble yes

在重寫AOF檔案時,Redis能夠在AOF檔案中使用RDB前導,以加快重寫和恢復速度。啟用此選項後,重寫的AOF檔案由兩個不同的節組成:RDB fileAOF tail

載入Redis時,會識別AOF檔案以Redis字串開頭,並載入帶字首的RDB檔案,然後繼續載入AOF尾部。

理論

優點

  • 資料的完整性和一致性更高,AOF的持久化透過使用不同的策略,最多丟失1秒的資料;
  • AOF檔案是一個只進行追加的日誌檔案,不需要寫入seek
  • Redis可以在 AOF檔案體積變得過大時,自動地在後臺對 AOF 進行重寫,重寫操作是絕對安全的;
  • AOF檔案記錄的寫入操作以Redis協議的格式儲存,容易讀懂,容易對檔案進行分析;

缺點

  • 對於相同的資料集來說,AOF檔案的體積通常要大於RDB檔案的體積;
  • 根據所使用的 fsync 策略,AOF的速度可能會慢於RDB

在一般情況下,每秒 fsync 的效能依然非常高,而關閉 fsync 可以讓 AOF 的速度和 RDB 一樣快, 即使在高負荷之下也是如此。不過在處理巨大的寫入載入時,RDB 可以提供更有保證的最大延遲時間(latency)。

對比與總結

如何選擇使用哪種持久化方式?

一般來說,如果想達到足以媲美 PostgreSQL 的資料安全性,應該同時使用兩種持久化功能。

如果非常關心資料,但仍然可以承受數分鐘以內的資料丟失,那麼可以只使用 RDB 持久化。

由於AOF持久化的實時性更好,即當程式意外退出時丟失的資料更少,因此AOF是目前主流的持久化方式。

有很多使用者都只使用AOF持久化,但我們並不推薦這種方式:因為定時生成 RDB 快照(snapshot)非常便於進行資料庫備份,並且 RDB 恢復資料集的速度也要比 AOF 恢復的速度要快。

AOF和RDB之間的相互作用

在版本號大於等於 2.4Redis 中,BGSAVE 執行的過程中,不可以執行 BGREWRITEAOF 。反過來說,在 BGREWRITEAOF 執行的過程中,也不可以執行 BGSAVE。這可以防止兩個 Redis 後臺程式同時對磁碟進行大量的I/O 操作。

如果 BGSAVE 正在執行,並且使用者顯示地呼叫 BGREWRITEAOF 命令,那麼伺服器將向使用者回覆一個 OK 狀態, 並告知使用者BGREWRITEAOF 已經被預定執行:一旦 BGSAVE 執行完畢,BGREWRITEAOF就會正式開始。

Redis 啟動時,如果 RDB持久化和 AOF 持久化都被開啟了, 那麼程式會優先使用 AOF 檔案來恢復資料集,因為 AOF檔案所儲存的資料通常是最完整的。

備份redis資料

  • 建立一個定期任務(cron job),每小時將一個 RDB 檔案備份到一個資料夾,並且每天將一個 RDB 檔案備份到另一個資料夾;
  • 確保快照的備份都帶有相應的日期和時間資訊,每次執行定期任務指令碼時,使用 find 命令來刪除過期的快照;
  • 至少每天一次,將 RDB 備份到你的資料中心之外,或者至少是備份到你執行 Redis 伺服器的物理機器之外。

效能建議

在實際應用時,因為RDB檔案只用作後備用途,建議只在slave上持久化RDB檔案,而且只需要15分鐘備份一次就夠了,只保留save 900 1這條規則。

如果開啟AOF,好處是在最惡劣情況下也只會丟失不超過2秒資料,啟動指令碼較簡單隻load自己的AOF檔案就可以了。代價一是帶來了持續的IO,二是AOF rewrite的最後將rewrite過程中產生的新資料寫到新檔案造成的阻塞幾乎是不可避免的。

只要硬碟許可,應該儘量減少AOF rewrite的頻率,AOF重寫的基礎大小預設值64M太小了,可以設定到5G以上。預設超過原大小的100%時重寫可以改到適當的數值。

如果不開啟AOF,僅靠Master-Slave Replication實現高可用性也可以。能省掉一大筆IO,也減少了rewrite時帶來的系統波動。代價是如果Master/Slave同時倒掉,會丟失十幾分鐘的資料,啟動指令碼也要比較兩個Master/Slave中的RDB檔案,載入較新的那個。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024420/viewspace-2924359/,如需轉載,請註明出處,否則將追究法律責任。

相關文章