1. 程式人生 > 實用技巧 >Redis持久化 - RDB和AOF

Redis持久化 - RDB和AOF

Redis持久化 - RDB和AOF

redisnosqllinuxphp資料庫 釋出於 2018-08-19

一、持久化的作用

1. 什麼是持久化

持久化(Persistence),即把資料(如記憶體中的物件)儲存到可永久儲存的儲存裝置中(如磁碟)。
持久化Redis所有資料保持在記憶體中,對資料的更新將非同步地儲存到磁碟上。

2. 持久化的實現方式

快照方式持久化

快照方式持久化就是在某時刻把所有資料進行完整備份。

例:Mysql的Dump方式、Redis的RDB方式。

寫日誌方式持久化

寫日誌方式持久化就是把使用者執行的所有寫指令(增刪改)備份到檔案中,還原資料時只需要把備份的所有指令重新執行一遍即可。

例:Mysql的Binlog、Redis的AOF、Hbase的HLog。

二、RDB

1. 什麼是RDB

RDB簡介

RDB持久化方式能夠在指定的時間間隔能對你的資料進行快照儲存。
在預設情況下, Redis 將資料庫快照儲存在名字為 dump.rdb的二進位制檔案中。
在 Redis 執行時, RDB 程式將當前記憶體中的資料庫快照儲存到磁碟檔案中, 在 Redis 重啟動時, RDB 程式可以通過載入 RDB 檔案來還原資料庫的狀態。

工作方式

當 Redis 需要儲存 dump.rdb 檔案時, 伺服器執行以下操作:

  1. Redis 呼叫forks。同時擁有父程序和子程序。
  2. 子程序將資料集寫入到一個臨時 RDB 檔案中。
  3. 當子程序完成對新 RDB 檔案的寫入時,Redis 用新 RDB 檔案替換原來的 RDB 檔案,並刪除舊的 RDB 檔案。

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

2. RDB的三種主要觸發機制

save命令(同步資料到磁碟上)

save命令執行一個同步操作,以RDB檔案的方式儲存所有資料的快照。

127.0.0.1:6379> save
OK

由於save命令是同步命令,會佔用Redis的主程序。若Redis資料非常多時,save命令執行速度會非常慢,阻塞所有客戶端的請求。
因此很少在生產環境直接使用SAVE 命令,可以使用BGSAVE 命令代替。如果在BGSAVE命令的儲存資料的子程序發生錯誤的時,用 SAVE命令儲存最新的資料是最後的手段。

bgsave命令(非同步儲存資料到磁碟上)

bgsave命令執行一個非同步操作,以RDB檔案的方式儲存所有資料的快照。

127.0.0.1:6379> bgsave
Background saving started

Redis使用Linux系統的fock()生成一個子程序來將DB資料儲存到磁碟,主程序繼續提供服務以供客戶端呼叫。
如果操作成功,可以通過客戶端命令LASTSAVE來檢查操作結果。

savebgsave對比

命令savebgsave
IO型別 同步 非同步
阻塞? 是(阻塞發生在fock(),通常非常快)
複雜度 O(n) O(n)
優點 不會消耗額外的記憶體 不阻塞客戶端命令
缺點 阻塞客戶端命令 需要fock子程序,消耗記憶體

自動生成RDB

除了手動執行savebgsave命令實現RDB持久化以外,Redis還提供了自動自動生成RDB的方式。

你可以通過配置檔案對 Redis 進行設定, 讓它在“ N 秒內資料集至少有 M 個改動”這一條件被滿足時, 自動進行資料集儲存操作。
比如說, 以下設定會讓 Redis 在滿足“ 60 秒內有至少有 1000 個鍵被改動”這一條件時, 自動進行資料集儲存操作:

save 60 1000

3. RDB相關配置

# RDB自動持久化規則
# 當 900 秒內有至少有 1 個鍵被改動時,自動進行資料集儲存操作
save 900 1
# 當 300 秒內有至少有 10 個鍵被改動時,自動進行資料集儲存操作
save 300 10
# 當 60 秒內有至少有 10000 個鍵被改動時,自動進行資料集儲存操作
save 60 10000

# RDB持久化檔名
dbfilename dump-<port>.rdb

# 資料持久化檔案儲存目錄
dir /var/lib/redis

# bgsave發生錯誤時是否停止寫入,通常為yes
stop-writes-on-bgsave-error yes

# rdb檔案是否使用壓縮格式
rdbcompression yes

# 是否對rdb檔案進行校驗和檢驗,通常為yes
rdbchecksum yes

4. RDB的優點

  1. RDB是一個非常緊湊的檔案,它儲存了某個時間點得資料集,非常適用於資料集的備份,比如你可以在每個小時報儲存一下過去24小時內的資料,同時每天儲存過去30天的資料,這樣即使出了問題你也可以根據需求恢復到不同版本的資料集。
  2. RDB是一個緊湊的單一檔案,很方便傳送到另一個遠端資料中心或者亞馬遜的S3(可能加密),非常適用於災難恢復。
  3. RDB在儲存RDB檔案時父程序唯一需要做的就是fork出一個子程序,接下來的工作全部由子程序來做,父程序不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的效能。
  4. 與AOF相比,在恢復大的資料集的時候,RDB方式會更快一些。

5. RDB的缺點

  1. 耗時、耗效能。RDB 需要經常fork子程序來儲存資料集到硬碟上,當資料集比較大的時候,fork的過程是非常耗時的,可能會導致Redis在一些毫秒級內不能響應客戶端的請求。如果資料集巨大並且CPU效能不是很好的情況下,這種情況會持續1秒,AOF也需要fork,但是你可以調節重寫日誌檔案的頻率來提高資料集的耐久度。
  2. 不可控、丟失資料。如果你希望在redis意外停止工作(例如電源中斷)的情況下丟失的資料最少的話,那麼RDB不適合你。雖然你可以配置不同的save時間點(例如每隔5分鐘並且對資料集有100個寫的操作),是Redis要完整的儲存整個資料集是一個比較繁重的工作,你通常會每隔5分鐘或者更久做一次完整的儲存,萬一在Redis意外宕機,你可能會丟失幾分鐘的資料。

三、AOF

1. 什麼是AOF

快照功能(RDB)並不是非常耐久(durable): 如果 Redis 因為某些原因而造成故障停機, 那麼伺服器將丟失最近寫入、且仍未儲存到快照中的那些資料。 從 1.1 版本開始, Redis 增加了一種完全耐久的持久化方式: AOF 持久化。
你可以在配置檔案中開啟AOF方式:

appendonly yes

開啟AOF後, 每當 Redis 執行一個改變資料集的命令時(比如 SET), 這個命令就會被追加到 AOF 檔案的末尾。這樣的話, 當 Redis 重新啟時, 程式就可以通過重新執行 AOF 檔案中的命令來達到重建資料集的目的。

AOF執行原理 - 建立

AOF執行原理 - 恢復

2. AOF持久化的三種策略

你可以通過配置檔案配置 Redis 多久才將資料 fsync 到磁碟一次。

always

每次有新命令追加到 AOF 檔案時就執行一次 fsync :非常慢,也非常安全。

everysec

每秒 fsync 一次:足夠快(和使用 RDB 持久化差不多),並且在故障時只會丟失 1 秒鐘的資料。
推薦(並且也是預設)的措施為每秒 fsync 一次, 這種 fsync 策略可以兼顧速度和安全性。

no

從不 fsync :將資料交給作業系統來處理,由作業系統來決定什麼時候同步資料。更快,也更不安全的選擇。

always、everysec、no對比

命令優點缺點
always 不丟失資料 IO開銷大,一般SATA磁碟只有幾百TPS
everysec 每秒進行與fsync,最多丟失1秒資料 可能丟失1秒資料
no 不用管 不可控

推薦(並且也是預設)的措施為每秒 fsync 一次, 這種 fsync 策略可以兼顧速度和安全性。

3. AOF重寫

因為 AOF 的運作方式是不斷地將命令追加到檔案的末尾, 所以隨著寫入命令的不斷增加, AOF 檔案的體積也會變得越來越大。舉個例子, 如果你對一個計數器呼叫了 100 次 INCR , 那麼僅僅是為了儲存這個計數器的當前值, AOF 檔案就需要使用 100 條記錄(entry)。然而在實際上, 只使用一條 SET 命令已經足以儲存計數器的當前值了, 其餘 99 條記錄實際上都是多餘的。
為了處理這種情況, Redis 支援一種有趣的特性: 可以在不打斷服務客戶端的情況下, 對 AOF 檔案進行重建(rebuild)。執行 bgrewriteaof 命令, Redis 將生成一個新的 AOF 檔案, 這個檔案包含重建當前資料集所需的最少命令。
Redis 2.2 需要自己手動執行 bgrewriteaof 命令; Redis 2.4 則可以通過配置自動觸發 AOF 重寫。

AOF重寫的作用

  • 減少磁碟佔用量
  • 加速資料恢復

AOF重寫的實現方式

  • bgrewriteaof 命令

    Redis bgrewriteaof 命令用於非同步執行一個 AOF(AppendOnly File)檔案重寫操作。重寫會建立一個當前AOF檔案的體積優化版本。
    即使 bgrewriteaof 執行失敗,也不會有任何資料丟失,因為舊的AOF檔案在 bgrewriteaof 成功之前不會被修改。
    AOF 重寫由 Redis 自行觸發,bgrewriteaof 僅僅用於手動觸發重寫操作。
    具體內容:

    • 如果一個子Redis是通過磁碟快照建立的,AOF重寫將會在RDB終止後才開始儲存。這種情況下BGREWRITEAOF任然會返回OK狀態碼。從Redis 2.6起你可以通過INFO命令檢視AOF重寫執行情況。
    • 如果只在執行的AOF重寫返回一個錯誤,AOF重寫將會在稍後一點的時間重新呼叫。

  • AOF重寫配置
配置名含義
auto-aof-rewrite-min-size 觸發AOF檔案執行重寫的最小尺寸
auto-aof-rewrite-percentage 觸發AOF檔案執行重寫的增長率
統計名含義
aof_current_size AOF檔案當前尺寸(位元組)
aof_base_size AOF檔案上次啟動和重寫時的尺寸(位元組)

AOF重寫自動觸發機制,需要同時滿足下面兩個條件:

  • aof_current_size > auto-aof-rewrite-min-size
  • (aof_current_size - aof_base_size) * 100 / aof_base_size > auto-aof-rewrite-percentage

假設 Redis 的配置項為:

auto-aof-rewrite-min-size 64mb
auto-aof-rewrite-percentage 100

當AOF檔案的體積大於64Mb,並且AOF檔案的體積比上一次重寫之久的體積大了至少一倍(100%)時,Redis將執行 bgrewriteaof 命令進行重寫。

AOF重寫的流程

3. AOF相關配置

# 開啟AOF持久化方式
appendonly yes

# AOF持久化檔名
appendfilename appendonly-<port>.aof

# 每秒把緩衝區的資料同步到磁碟
appendfsync everysec

# 資料持久化檔案儲存目錄
dir /var/lib/redis

# 是否在執行重寫時不同步資料到AOF檔案
# 這裡的 yes,就是執行重寫時不同步資料到AOF檔案
no-appendfsync-on-rewrite yes

# 觸發AOF檔案執行重寫的最小尺寸
auto-aof-rewrite-min-size 64mb

# 觸發AOF檔案執行重寫的增長率
auto-aof-rewrite-percentage 100

4. AOF的優點

  1. 使用AOF 會讓你的Redis更加耐久: 你可以使用不同的fsync策略:無fsync,每秒fsync,每次寫的時候fsync。使用預設的每秒fsync策略,Redis的效能依然很好(fsync是由後臺執行緒進行處理的,主執行緒會盡力處理客戶端請求),一旦出現故障,你最多丟失1秒的資料。
  2. AOF檔案是一個只進行追加的日誌檔案,所以不需要寫入seek,即使由於某些原因(磁碟空間已滿,寫的過程中宕機等等)未執行完整的寫入命令,你也也可使用redis-check-aof工具修復這些問題。
  3. Redis 可以在 AOF 檔案體積變得過大時,自動地在後臺對 AOF 進行重寫: 重寫後的新 AOF 檔案包含了恢復當前資料集所需的最小命令集合。 整個重寫操作是絕對安全的,因為 Redis 在建立新 AOF 檔案的過程中,會繼續將命令追加到現有的 AOF 檔案裡面,即使重寫過程中發生停機,現有的 AOF 檔案也不會丟失。 而一旦新 AOF 檔案建立完畢,Redis 就會從舊 AOF 檔案切換到新 AOF 檔案,並開始對新 AOF 檔案進行追加操作。
  4. AOF 檔案有序地儲存了對資料庫執行的所有寫入操作, 這些寫入操作以 Redis 協議的格式儲存, 因此 AOF 檔案的內容非常容易被人讀懂, 對檔案進行分析(parse)也很輕鬆。 匯出(export) AOF 檔案也非常簡單: 舉個例子, 如果你不小心執行了 FLUSHALL 命令, 但只要 AOF 檔案未被重寫, 那麼只要停止伺服器, 移除 AOF 檔案末尾的 FLUSHALL 命令, 並重啟 Redis , 就可以將資料集恢復到 FLUSHALL 執行之前的狀態。

5. AOF的缺點

  1. 對於相同的資料集來說,AOF 檔案的體積通常要大於 RDB 檔案的體積。
  2. 根據所使用的 fsync 策略,AOF 的速度可能會慢於 RDB 。 在一般情況下, 每秒 fsync 的效能依然非常高, 而關閉 fsync 可以讓 AOF 的速度和 RDB 一樣快, 即使在高負荷之下也是如此。 不過在處理巨大的寫入載入時,RDB 可以提供更有保證的最大延遲時間(latency)。

四、RDB和AOF的抉擇

1. RDB 和 AOF 對比

-RDBAOF
啟動優先順序
體積
恢復速度
資料安全性 丟資料 根據策略決定

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

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

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

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