前言 在之前的博文中已經詳細的介紹了redis4.0基礎部分,並且在memcache和redis對比中提及redis提供可靠的數據持久化方案,而memcache沒有數據持久化方案,本篇博文將詳細介紹redis4.0所提供的持久化方案:RDB持久化和AOF持久化以及redis4.0新特性混合持久化。這 ...
前言
在之前的博文中已經詳細的介紹了redis4.0基礎部分,並且在memcache和redis對比中提及redis提供可靠的數據持久化方案,而memcache沒有數據持久化方案,本篇博文將詳細介紹redis4.0所提供的持久化方案:RDB持久化和AOF持久化以及redis4.0新特性混合持久化。這裡將從原理到配置以及相關實踐進行說明,希望能對你有所幫助。
一、RDB持久化
簡介
RDB持久化方式是通過快照(snapshotting)完成的,當符合一定條件時,redis會自動將記憶體中所有數據以二進位方式生成一份副本並存儲在硬碟上。當redis重啟時,並且AOF持久化未開啟時,redis會讀取RDB持久化生成的二進位文件(預設名稱dump.rdb,可通過設置dbfilename修改)進行數據恢復,對於持久化信息可以用過命令“info Persistence”查看。
快照文件位置
RDB快照文件存儲文件位置由dir配置參數指明,文件名由dbfilename指定,如下:
快照觸發條件
RDB生成快照可自動促發,也可以使用命令手動觸發,以下是redis觸發執行快照條件,後續會對每個條件詳細說明:
- 客戶端執行命令save和bgsave會生成快照;
- 根據配置文件save m n規則進行自動快照;
- 主從複製時,從庫全量複製同步主庫數據,此時主庫會執行bgsave命令進行快照;
- 客戶端執行資料庫清空命令FLUSHALL時候,觸發快照;
- 客戶端執行shutdown關閉redis時,觸發快照;
save命令觸發
客戶端執行save命令,該命令強制redis執行快照,這時候redis處於阻塞狀態,不會響應任何其他客戶端發來的請求,直到RDB快照文件執行完畢,所以請慎用。
實踐操作:
首先使用info Persistence查看最近一次持久化時間:
此時我們執行save命令,並再次查看最新快照保存時間已經是最新一次時間:
當然你也可以直接查看RDB數據文件目錄下的RDB文件最新時間:
bgsave命令觸發
bgsave命令可以理解為background save即:“後臺保存”。當執行bgsave命令時,redis會fork出一個子進程來執行快照生成操作,需要註意的redis是在fork子進程這個簡短的時間redis是阻塞的(此段時間不會響應客戶端請求,),當子進程創建完成以後redis響應客戶端請求。其實redis自動快照也是使用bgsave來完成的。
為了能清楚瞭解bgsave工作過程,以下將圖文詳細描述其工作過程:
對上述過程描述:
- 客戶端執行bgsave命令,redis主進程收到指令並判斷此時是否在執行bgrewriteaof(AOF文件重新過程,後續會講解),如果此時正好在執行則bgsave直接返回,不fork子進程,如果沒有執行bgrewriteaof重寫AOF文件,則進入下一個階段;
- 主進程調用fork方法創建子進程,在創建過程中redis主進程阻塞,所以不能響應客戶端請求;
- 子進程創建完成以後,bgsave命令返回“Background saving started”,此時標志著redis可以響應客戶端請求了;
- 子經常根據主進程的記憶體副本創建臨時快照文件,當快照文件完成以後對原快照文件進行替換;
- 子進程發送信號給redis主進程完成快照操作,主進程更新統計信息(info Persistence可查看),子進程退出;
實踐操作:
執行bgsave
查看日誌,能看到6MB文件記憶體副本寫到了磁碟上,同時列印“Background saving terminated with success”代表文件bgsave操作完成。
此時我們查看統計信息最後一次RDB保存時間已經更新:
save m n規則觸發
save m n規則說明:在指定的m秒內,redis中有n個鍵發生改變,則自動觸發bgsave。該規則預設也在redis.conf中進行了配置,並且可組合使用,滿足其中一個規則,則觸發bgsave,在上篇博文也進行瞭解釋,如下:
以save 900 1為例,表明當900秒內至少有一個鍵發生改變時候,redis觸發bgsave操作。
實踐操作:
我們改變一個鍵,滿足save 900 1 :
此時查看redis日誌,會發現redis立即響應開始bgsave操作:
FLUSHALL觸發
flushall命令用於清空資料庫,請慎用,當我們使用了則表明我們需要對數據進行清空,那redis當然需要對快照文件也進行清空,所以會觸發bgsave。
實踐操作:
日誌:
shutdown觸發
shutdown命令觸發就不用說了,redis在關閉前處於安全形度將所有數據全部保存下來,以便下次啟動會恢復。
實踐操作:
可以使用客戶端連入執行shutdown命令,也可以直接使用腳本關閉redis,這裡我使用init腳本(系統centos6.X)。
查看日誌:
主從觸發
在redis主從複製中,從節點執行全量複製操作,主節點會執行bgsave命令,並將rdb文件發送給從節點,該過程會在複製篇中進行闡述。
故障恢復
上面提及到過,當redis意外崩潰或者關閉再次啟動時,此時AOF持久化未開啟時(預設未開啟),將使用RDB快照文件恢複數據。
下麵我們停用redis服務來模擬故障情況,讓再啟動redis服務:
觀察日誌會發現,啟動時候load RDB文件。
RDB持久化配置
save m n #配置快照(rdb)促發規則,格式:save <seconds> <changes> #save 900 1 900秒內至少有1個key被改變則做一次快照 #save 300 10 300秒內至少有300個key被改變則做一次快照 #save 60 10000 60秒內至少有10000個key被改變則做一次快照 #關閉該規則使用svae “” dbfilename dump.rdb #rdb持久化存儲資料庫文件名,預設為dump.rdb stop-write-on-bgsave-error yes #yes代表當使用bgsave命令持久化出錯時候停止寫RDB快照文件,no表明忽略錯誤繼續寫文件。 rdbchecksum yes #在寫入文件和讀取文件時是否開啟rdb文件檢查,檢查是否有無損壞,如果在啟動是檢查發現損壞,則停止啟動。 dir "/etc/redis" #數據文件存放目錄,rdb快照文件和aof文件都會存放至該目錄,請確保有寫許可權 rdbcompression yes #是否開啟RDB文件壓縮,該功能可以節約磁碟空間
二、AOF持久化
簡介
當redis存儲非臨時數據時,為了降低redis故障而引起的數據丟失,redis提供了AOF(Append Only File)持久化,從單詞意思講,將命令追加到文件。AOF可以將Redis執行的每一條寫命令追加到磁碟文件(appendonly.aof)中,在redis啟動時候優先選擇從AOF文件恢複數據。由於每一次的寫操作,redis都會記錄到文件中,所以開啟AOF持久化會對性能有一定的影響,但是大部分情況下這個影響是可以接受的,我們可以使用讀寫速率高的硬碟提高AOF性能。與RDB持久化相比,AOF持久化數據丟失更少,其消耗記憶體更少(RDB方式執行bgsve會有記憶體拷貝)。
開啟AOF
預設情況下,redis是關閉了AOF持久化,開啟AOF通過配置appendonly為yes開啟,我們修改配置文件或者在命令行直接使用config set修改,在用config rewrite同步到配置文件。通過客戶端修改好處是不用重啟redis,AOF持久化直接生效。
AOF持久化過程
redisAOF持久化過程可分為以下階段:
1.追加寫入
redis將每一條寫命令以redis通訊協議添加至緩衝區aof_buf,這樣的好處在於在大量寫請求情況下,採用緩衝區暫存一部分命令隨後根據策略一次性寫入磁碟,這樣可以減少磁碟的I/O次數,提高性能。
2.同步命令到硬碟
當寫命令寫入aof_buf緩衝區後,redis會將緩衝區的命令寫入到文件,redis提供了三種同步策略,由配置參數appendfsync決定,下麵是每個策略所對應的含義:
- no:不使用fsync方法同步,而是交給操作系統write函數去執行同步操作,在linux操作系統中大約每30秒刷一次緩衝。這種情況下,緩衝區數據同步不可控,並且在大量的寫操作下,aof_buf緩衝區會堆積會越來越嚴重,一旦redis出現故障,數據丟失嚴重。
- always:表示每次有寫操作都調用fsync方法強制內核將數據寫入到aof文件。這種情況下由於每次寫命令都寫到了文件中, 雖然數據比較安全,但是因為每次寫操作都會同步到AOF文件中,所以在性能上會有影響,同時由於頻繁的IO操作,硬碟的使用壽命會降低。
- everysec:數據將使用調用操作系統write寫入文件,並使用fsync每秒一次從內核刷新到磁碟。 這是折中的方案,兼顧性能和數據安全,所以redis預設推薦使用該配置。
3.文件重寫(bgrewriteaof)
當開啟的AOF時,隨著時間推移,AOF文件會越來越大,當然redis也對AOF文件進行了優化,即觸發AOF文件重寫條件(後續會說明)時候,redis將使用bgrewriteaof對AOF文件進行重寫。這樣的好處在於減少AOF文件大小,同時有利於數據的恢復。
為什麼重寫?比如先後執行了“set foo bar1 set foo bar2 set foo bar3” 此時AOF文件會記錄三條命令,這顯然不合理,因為文件中應只保留“set foo bar3”這個最後設置的值,前面的set命令都是多餘的,下麵是一些重寫時候策略:
- 重覆或無效的命令不寫入文件
- 過期的數據不再寫入文件
- 多條命令合併寫入(當多個命令能合併一條命令時候會對其優化合併作為一個命令寫入,例如“RPUSH list1 a RPUSH list1 b" 合併為“RPUSH list1 a b” )
重寫觸發條件
AOF文件觸發條件可分為手動觸發和自動觸發:
手動觸發:客戶端執行bgrewriteaof命令。
自動觸發:自動觸發通過以下兩個配置協作生效:
- auto-aof-rewrite-min-size: AOF文件最小重寫大小,只有當AOF文件大小大於該值時候才可能重寫,4.0預設配置64mb。
- auto-aof-rewrite-percentage:當前AOF文件大小和最後一次重寫後的大小之間的比率等於或者等於指定的增長百分比,如100代表當前AOF文件是上次重寫的兩倍時候才重寫。
redis開啟在AOF功能開啟的情況下,會維持以下三個變數
- 記錄當前AOF文件大小的變數aof_current_size。
- 記錄最後一次AOF重寫之後,AOF文件大小的變數aof_rewrite_base_size。
- 增長百分比變數aof_rewrite_perc。
每次當serverCron(伺服器周期性操作函數)函數執行時,它會檢查以下條件是否全部滿足,如果全部滿足的話,就觸發自動的AOF重寫操作:
- 沒有BGSAVE命令(RDB持久化)/AOF持久化在執行;
- 沒有BGREWRITEAOF在進行;
- 當前AOF文件大小要大於server.aof_rewrite_min_size的值;
- 當前AOF文件大小和最後一次重寫後的大小之間的比率等於或者大於指定的增長百分比(auto-aof-rewrite-percentage參數)
重寫過程
AOF文件重寫過程與RDB快照bgsave工作過程有點相似,都是通過fork子進程,由子進程完成相應的操作,同樣的在fork子進程簡短的時間內,redis是阻塞的,以下圖文說明其重寫過程:
過程說明:
aof_rewrite_buf 代表重寫緩衝區 aof_buf代表寫寫命令存放的緩衝區
1.開始bgrewriteaof,判斷當前有沒有bgsave命令(RDB持久化)/bgrewriteaof在執行,倘若有,則這些命令執行完成以後在執行。
2.主進程fork出子進程,在這一個短暫的時間內,redis是阻塞的。
3.主進程fork完子進程繼續接受客戶端請求,所有寫命令依然寫入AOF文件緩衝區並根據appendfsync策略同步到磁碟,保證原有AOF文件完整和正確。由於fork的子進程僅僅只共用主進程fork時的記憶體,因此Redis使用採用重寫緩衝區(aof_rewrite_buf)機制保存fork之後的客戶端的寫請求,防止新AOF文件生成期間丟失這部分數據。此時,客戶端的寫請求不僅僅寫入原來aof_buf緩衝,還寫入重寫緩衝區(aof_rewrite_buf)。
4.子進程通過記憶體快照,按照命令重寫策略寫入到新的AOF文件。
4.1子進程寫完新的AOF文件後,向主進程發信號,父進程更新統計信息。
4.2主進程把AOFaof_rewrite_buf中的數據寫入到新的AOF文件(避免寫文件是數據丟失)。
5.使用新的AOF文件覆蓋舊的AOF文件,標誌AOF重寫完成。
AOF實現本質
AOF實現本質是基於redis通訊協議,將命令以純文本的方式寫入到文件中。
redis協議:
首先Redis是以行來劃分,每行以\r\n行結束。每一行都有一個消息頭,消息頭共分為5種分別如下:
(+) 表示一個正確的狀態信息,具體信息是當前行+後面的字元。
(-) 表示一個錯誤信息,具體信息是當前行-後面的字元。
(*) 表示消息體總共有多少行,不包括當前行,*後面是具體的行數。
($) 表示下一行數據長度,不包括換行符長度\r\n,$後面則是對應的長度的數據。
(:) 表示返回一個數值,:後面是相應的數位元組符。
我們可以直接查看AOF文件中的格式,如下圖:
數據恢復
之前已經提到當AOF開啟時候,redis數據恢復優先選用AOF進行數據恢復,以下使用停止redis來模擬redis故障,然後在重寫啟動進行恢復。
查看日誌會發現數據恢復已經變成從AOF(append only file)文件中恢復:
AOF配置參數
auto-aof-rewrite-min-size 64mb #AOF文件最小重寫大小,只有當AOF文件大小大於該值時候才可能重寫,4.0預設配置64mb。 auto-aof-rewrite-percentage 100 #當前AOF文件大小和最後一次重寫後的大小之間的比率等於或者等於指定的增長百分比,如100代表當前AOF文件是上次重寫的兩倍時候才重寫。 appendfsync everysec #no:不使用fsync方法同步,而是交給操作系統write函數去執行同步操作,在linux操作系統中大約每30秒刷一次緩衝。這種情況下,緩衝區數據同步不可控,並且在大量的寫操作下,aof_buf緩衝區會堆積會越來越嚴重,一旦redis出現故障,數據 #always:表示每次有寫操作都調用fsync方法強制內核將數據寫入到aof文件。這種情況下由於每次寫命令都寫到了文件中, 雖然數據比較安全,但是因為每次寫操作都會同步到AOF文件中,所以在性能上會有影響,同時由於頻繁的IO操作,硬碟的使用壽命會降低。 #everysec:數據將使用調用操作系統write寫入文件,並使用fsync每秒一次從內核刷新到磁碟。 這是折中的方案,兼顧性能和數據安全,所以redis預設推薦使用該配置。 aof-load-truncated yes #當redis突然運行崩潰時,會出現aof文件被截斷的情況,Redis可以在發生這種情況時退出並載入錯誤,以下選項控制此行為。 #如果aof-load-truncated設置為yes,則載入截斷的AOF文件,Redis伺服器啟動發出日誌以通知用戶該事件。 #如果該選項設置為no,則服務將中止並顯示錯誤並停止啟動。當該選項設置為no時,用戶需要在重啟之前使用“redis-check-aof”實用程式修複AOF文件在進行啟動。 appendonly no #yes開啟AOF,no關閉AOF appendfilename appendonly.aof #指定AOF文件名,4.0無法通過config set 設置,只能通過修改配置文件設置。 dir /etc/redis #RDB文件和AOF文件存放目錄
實踐
實踐操作這裡使用手動執bgrewriteaof演示重寫。
查看日誌:
三、RDB-AOF混合持久化
簡介
redis4.0相對與3.X版本其中一個比較大的變化是4.0添加了新的混合持久化方式。前面已經詳細介紹了AOF持久化以及RDB持久化,這裡介紹的混合持久化就是同時結合RDB持久化以及AOF持久化混合寫入AOF文件。這樣做的好處是可以結合 rdb 和 aof 的優點, 快速載入同時避免丟失過多的數據,缺點是 aof 裡面的 rdb 部分就是壓縮格式不再是 aof 格式,可讀性差。
開啟混合持久化
4.0版本的混合持久化預設關閉的,通過aof-use-rdb-preamble配置參數控制,yes則表示開啟,no表示禁用,預設是禁用的,可通過config set修改。
混合持久化過程
瞭解了AOF持久化過程和RDB持久化過程以後,混合持久化過程就相對簡單了。
混合持久化同樣也是通過bgrewriteaof完成的,不同的是當開啟混合持久化時,fork出的子進程先將共用的記憶體副本全量的以RDB方式寫入aof文件,然後在將重寫緩衝區的增量命令以AOF方式寫入到文件,寫入完成後通知主進程更新統計信息,並將新的含有RDB格式和AOF格式的AOF文件替換舊的的AOF文件。簡單的說:新的AOF文件前半段是RDB格式的全量數據後半段是AOF格式的增量數據,如下圖:
數據恢復
當我們開啟了混合持久化時,啟動redis依然優先載入aof文件,aof文件載入可能有兩種情況如下:
- aof文件開頭是rdb的格式, 先載入 rdb內容再載入剩餘的 aof。
- aof文件開頭不是rdb的格式,直接以aof格式載入整個文件。
實踐
開啟混合持久化,併在開啟後立馬執行寫操作,為了證實混合持久化的後半部分AOF過程
查看日誌:
此時的aof文件已經和只開啟AOF持久化文件不一樣了,上半部分是RDB持久化的數據,下半部分是AOF格式數據。
四、優缺點
RDB
優點:
-
RDB 是一個非常緊湊(compact)的文件,體積小,因此在傳輸速度上比較快,因此適合災難恢復。
-
RDB 可以最大化 Redis 的性能:父進程在保存 RDB 文件時唯一要做的就是 fork 出一個子進程,然後這個子進程就會處理接下來的所有保存工作,父進程無須執行任何磁碟 I/O 操作。
-
RDB 在恢復大數據集時的速度比 AOF 的恢復速度要快。
缺點:
- RDB是一個快照過程,無法完整的保存所以數據,尤其在數據量比較大時候,一旦出現故障丟失的數據將更多。
- 當redis中數據集比較大時候,RDB由於RDB方式需要對數據進行完成拷貝並生成快照文件,fork的子進程會耗CPU,並且數據越大,RDB快照生成會越耗時。
- RDB文件是特定的格式,閱讀性差,由於格式固定,可能存在不相容情況。
AOF
優點:
- 數據更完整,秒級數據丟失(取決於設置fsync策略)。
- 相容性較高,由於是基於redis通訊協議而形成的命令追加方式,無論何種版本的redis都相容,再者aof文件是明文的,可閱讀性較好。
缺點:
- 數據文件體積較大,即使有重寫機制,但是在相同的數據集情況下,AOF文件通常比RDB文件大。
- 相對RDB方式,AOF速度慢於RDB,並且在數據量大時候,恢復速度AOF速度也是慢於RDB。
- 由於頻繁地將命令同步到文件中,AOF持久化對性能的影響相對RDB較大,但是對於我們來說是可以接受的。
混合持久化
優點:
- 混合持久化結合了RDB持久化 和 AOF 持久化的優點, 由於絕大部分都是RDB格式,載入速度快,同時結合AOF,增量的數據以AOF方式保存了,數據更少的丟失。
缺點:
- 相容性差,一旦開啟了混合持久化,在4.0之前版本都不識別該aof文件,同時由於前部分是RDB格式,閱讀性較差
五、相關命令
aof文件檢查
redis-check-aof /etc/redis/appendonly.aof
rdb文件檢查
redis-check-rdb /etc/redis/dump.rdb
查看持久化信息
info Persistence
查看狀態信息
info stats
以上是所有內容,希望對你有幫助~