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 檔案時, 伺服器執行以下操作:
- Redis 呼叫forks。同時擁有父程序和子程序。
- 子程序將資料集寫入到一個臨時 RDB 檔案中。
- 當子程序完成對新 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來檢查操作結果。
save
與bgsave
對比
命令 | save | bgsave |
---|---|---|
IO型別 | 同步 | 非同步 |
阻塞? | 是 | 是(阻塞發生在fock(),通常非常快) |
複雜度 | O(n) | O(n) |
優點 | 不會消耗額外的記憶體 | 不阻塞客戶端命令 |
缺點 | 阻塞客戶端命令 | 需要fock子程序,消耗記憶體 |
自動生成RDB
除了手動執行save
和bgsave
命令實現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的優點
- RDB是一個非常緊湊的檔案,它儲存了某個時間點得資料集,非常適用於資料集的備份,比如你可以在每個小時報儲存一下過去24小時內的資料,同時每天儲存過去30天的資料,這樣即使出了問題你也可以根據需求恢復到不同版本的資料集。
- RDB是一個緊湊的單一檔案,很方便傳送到另一個遠端資料中心或者亞馬遜的S3(可能加密),非常適用於災難恢復。
- RDB在儲存RDB檔案時父程序唯一需要做的就是fork出一個子程序,接下來的工作全部由子程序來做,父程序不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的效能。
- 與AOF相比,在恢復大的資料集的時候,RDB方式會更快一些。
5. RDB的缺點
- 耗時、耗效能。RDB 需要經常fork子程序來儲存資料集到硬碟上,當資料集比較大的時候,fork的過程是非常耗時的,可能會導致Redis在一些毫秒級內不能響應客戶端的請求。如果資料集巨大並且CPU效能不是很好的情況下,這種情況會持續1秒,AOF也需要fork,但是你可以調節重寫日誌檔案的頻率來提高資料集的耐久度。
- 不可控、丟失資料。如果你希望在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的優點
- 使用AOF 會讓你的Redis更加耐久: 你可以使用不同的fsync策略:無fsync,每秒fsync,每次寫的時候fsync。使用預設的每秒fsync策略,Redis的效能依然很好(fsync是由後臺執行緒進行處理的,主執行緒會盡力處理客戶端請求),一旦出現故障,你最多丟失1秒的資料。
- AOF檔案是一個只進行追加的日誌檔案,所以不需要寫入seek,即使由於某些原因(磁碟空間已滿,寫的過程中宕機等等)未執行完整的寫入命令,你也也可使用redis-check-aof工具修復這些問題。
- Redis 可以在 AOF 檔案體積變得過大時,自動地在後臺對 AOF 進行重寫: 重寫後的新 AOF 檔案包含了恢復當前資料集所需的最小命令集合。 整個重寫操作是絕對安全的,因為 Redis 在建立新 AOF 檔案的過程中,會繼續將命令追加到現有的 AOF 檔案裡面,即使重寫過程中發生停機,現有的 AOF 檔案也不會丟失。 而一旦新 AOF 檔案建立完畢,Redis 就會從舊 AOF 檔案切換到新 AOF 檔案,並開始對新 AOF 檔案進行追加操作。
- AOF 檔案有序地儲存了對資料庫執行的所有寫入操作, 這些寫入操作以 Redis 協議的格式儲存, 因此 AOF 檔案的內容非常容易被人讀懂, 對檔案進行分析(parse)也很輕鬆。 匯出(export) AOF 檔案也非常簡單: 舉個例子, 如果你不小心執行了 FLUSHALL 命令, 但只要 AOF 檔案未被重寫, 那麼只要停止伺服器, 移除 AOF 檔案末尾的 FLUSHALL 命令, 並重啟 Redis , 就可以將資料集恢復到 FLUSHALL 執行之前的狀態。
5. AOF的缺點
- 對於相同的資料集來說,AOF 檔案的體積通常要大於 RDB 檔案的體積。
- 根據所使用的 fsync 策略,AOF 的速度可能會慢於 RDB 。 在一般情況下, 每秒 fsync 的效能依然非常高, 而關閉 fsync 可以讓 AOF 的速度和 RDB 一樣快, 即使在高負荷之下也是如此。 不過在處理巨大的寫入載入時,RDB 可以提供更有保證的最大延遲時間(latency)。
四、RDB和AOF的抉擇
1. RDB 和 AOF 對比
- | RDB | AOF |
---|---|---|
啟動優先順序 | 低 | 高 |
體積 | 小 | 大 |
恢復速度 | 快 | 慢 |
資料安全性 | 丟資料 | 根據策略決定 |
2. 如何選擇使用哪種持久化方式?
一般來說, 如果想達到足以媲美 PostgreSQL 的資料安全性, 你應該同時使用兩種持久化功能。
如果你非常關心你的資料, 但仍然可以承受數分鐘以內的資料丟失, 那麼你可以只使用 RDB 持久化。
有很多使用者都只使用 AOF 持久化, 但並不推薦這種方式: 因為定時生成 RDB 快照(snapshot)非常便於進行資料庫備份, 並且 RDB 恢復資料集的速度也要比 AOF 恢復的速度要快。