Redis 的落地策略

語言: CN / TW / HK

因為之前使用redis一般都只做熱資料處理,沒有考慮過落地方案,因此,通過很多次不同的交流,發現落地也挺重要的,特來學習一般。

落地策略

我們知道,redis是純記憶體資料庫,一旦發生宕機,資料就會丟失,因此,Redis 的落地策略其實就是持久化(Persistence),主要有以下2種策略:

  1. RDB: 定時快照方式(snapshot)
  2. AOF: 基於語句追加檔案的方式

RDB

RDB 檔案非常緊湊,它儲存了 Redis 某個時間點上的資料集。RDB 恢復大資料集時速度要比 AOF 快。但是 RDB 不適合那些對時效性要求很高的業務,因為它只儲存了快照,在進行恢復時會導致一些時間內的資料丟失。實際在進行備份時,Redis 主要依靠 rdbSave() 函式,然後有兩個命令會呼叫這個函式 SAVE 和 BGSAVE,前者會同步呼叫,阻塞主程序導致會有短暫的 Redis-server 停止工作,後者會 fork 出子程序非同步處理。

在呼叫 SAVE 或者 BGSAVE 時,只有釋出和訂閱功能的命令可以正常執行,因為這個模組和伺服器的其他模組是隔離的。 下面的命令表示: “60 秒內有至少有 1000 個鍵被改動”時進行RDB檔案備份。

redis-server> SAVE 60 1000

開頭的REDIS表示這是一個 RDB 檔案,然後緊跟著 redis 的版本號,SELECT-DB 和 KEY-VALUES-PAIRS 構成了對一個數據庫中的所有資料記錄,其中 KEY-VALUES-PAIRS 具體結構如下,後面兩個就不用說了。

AOF

AOF 可以通過設定的 fsync 策略配置,如果未設定 fsync ,AOF 的預設策略為每秒鐘 fsync 一次,在這種配置下, fsync 會在後臺執行緒執行,所以主執行緒不會受到打擾。但是像 AOF 這種策略會導致追加的檔案非常大,而且在恢復大資料時非常緩慢,因為要把所有會導致寫資料庫的命令都重新執行一遍。AOF檔案中實際儲存的是 Redis 協議下的命令記錄,因此非常易讀。

當然 Redis 考慮到了 AOF 檔案過大的問題,因此引入了 BGREWRITEAOF 命令進行重建 AOF 檔案,保證可以減少大量無用的重複寫操作。重建命令並不會去分析已有的 AOF 檔案,而是將當前資料庫的快照儲存。

在 AOF 檔案重寫時,Redis 的具體邏輯如下:

  1. Redis 首先 fork 出一個子程序,子程序將新 AOF 檔案的內容寫入到臨時檔案。
  2. 對於所有新執行的寫入命令,父程序一邊將它們累積到一個快取中,一邊將這些改動追加到現有 AOF 檔案的末尾: 這樣即使在重寫的中途發生停機,現有的 AOF 檔案也還是安全的。
  3. 當子程序完成重寫工作時,它給父程序傳送一個訊號,父程序在接收到訊號之後,將快取中的所有資料追加到新 AOF 檔案的末尾。
  4. 現在 Redis 原子地用新檔案替換舊檔案,之後所有命令都會直接追加到新 AOF 檔案的末尾。

Redis 會維持一個預設的AOF重寫策略,噹噹前的AOF檔案比上次重寫之後的檔案大小增大了一倍時,就會自動在後臺重寫AOF。

從策略方式來看,AOF檔案模式類似於mysql的binlog,是做一個歸檔日誌,屬於邏輯日誌。

AOF與RDB的優缺點和適用場景

RDB持久化是在指定的時間間隔內將記憶體中的資料集快照寫入磁碟中,fork一個子程序,先將資料集寫入臨時檔案,寫入成功後,再替換之前的檔案,用二進位制壓縮儲存。具體操作:遍歷hash table,利用copy on write,把整個db dump儲存下來。save, shutdown, slave 命令會觸發這個操作。

特點:粒度比較大,如果save, shutdown, slave 之前crash了,則中間的操作沒辦法恢復。

AOF持久化以日誌的形式記錄伺服器所處理的每一個寫、刪除操作,查詢操作不會記錄,以文字的方式記錄,可以開啟檔案看到詳細的操作記錄。Redis 還可以在後臺對 AOF 檔案進行重寫(rewrite),使得 AOF 檔案的體積不會超出儲存資料集狀態所需的實際大小。Redis 還可以同時使用 AOF 持久化和 RDB 持久化。 在這種情況下, 當 Redis 重啟時, 它會優先使用 AOF 檔案來還原資料集, 因為 AOF 檔案儲存的資料集通常比 RDB 檔案所儲存的資料集更完整。你甚至可以關閉持久化功能,讓資料只在伺服器執行時存在。

特點:粒度較小,crash之後,只有crash之前沒有來得及做日誌的操作沒辦法恢復。

選擇的標準,就是看系統是願意犧牲一些效能,換取更高的快取一致性(aof),還是願意寫操作頻繁的時候,不啟用備份來換取更高的效能,待手動執行save的時候,再做備份(rdb)。rdb這個就更有些 eventually consistent的意思了。

分享到: