RDB持久化方式是經過快照(snapshotting)完成的,當符合必定條件時,redis會自動將內存中全部數據以二進制方式生成一份副本並存儲在硬盤上。當redis重啓時,而且AOF持久化未開啓時,redis會讀取RDB持久化生成的二進制文件(默認名稱dump.rdb,可經過設置dbfilename修改)進行數據恢復,對於持久化信息能夠用過命令「info Persistence」查看。linux
該命令會由worker thread
執行,所以會阻塞 redis 的 worker
,期間不會響應任何其餘客戶端發來的請求,直到RDB快照文件執行完畢,因此慎用。redis
info persistence # rdb_last_save_time:1570126868 save info persistence # rdb_last_save_time:1570126928
bgsave
「後臺保存」。與save 最大的差別爲它並是由 worker thread
執行的,而是由redis fork
出子進程,交由子進程來完成持久化操做。shell
redis
是在fork
子進程這個時間段內 redis是阻塞
的(此段時間不會響應客戶端請求),當子進程建立完成之後redis響應客戶端請求。數據庫
redis
不會再控制檯顯示完成信息,可是會寫入日誌。緩存
客戶端執行bgsave命令,redis主進程收到指令並判斷此時是否在執行bgrewriteaof(AOF文件從新過程,後續會講解),若是此時正好在執行則bgsave直接返回,不fork子進程,若是沒有執行bgrewriteaof重寫AOF文件,則進入下一個階段;安全
主進程調用fork方法建立子進程,在建立子進程
過程當中redis主進程阻塞,因此不能響應客戶端請求;服務器
子進程建立完成之後,bgsave
命令返回Background saving started
,此時標誌着redis能夠響應客戶端請求了;app
子常常根據主進程的內存副本建立臨時快照文件,當快照文件完成之後對原快照文件進行替換;函數
子進程發送信號給redis主進程完成快照操做,主進程更新統計信息(info Persistence可查看),子進程退出;性能
bgsave Background saving started # 子進程建立成功,它會去 完成持久化操做
config get logfile 11) "logfile" 12) "/var/log/redis/redis-server.log" cat "/var/log/redis/redis-server.log" 2497:M 04 Oct 2019 10:26:46.764 * Background saving started by pid 28960 # 開始後臺 持久化 2497:M 04 Oct 2020 10:26:46.772 * Background saving terminated with success # 後臺持久化完成
查看配置的方法:
1 查看配置文件
2 在redis 中查看當前 redis 的配置
CONFIG get * # 獲取全部的配置 CONFIG get dir # 獲取 快照文件 保存的 位置 CONFIG get dbfilename # 獲取 快照文件 的文件名
配置文件中 dir
指定
配置文件中 dbfilename
配置文件中 rdbcompression
default:yes
設置存儲至本地數據庫時是否壓縮數據,默認爲yes,採用LZF壓縮
yes 會耗費必定的CPU資源,默認是 yes 。
no 會使存儲的文件變大(巨大)
配置文件中 yesrdbchecksumy
default: yes
yes 會消耗一部分CPU資源,可是數據相對安全不容易損壞
no 能夠節約讀寫性過程約10%時間消耗,可是存儲必定的數據損壞風險
配置文件中 stop-writes-on-bgsave-error
default: yes
後臺存儲過程當中若是出現錯誤線程,是否中止保存操做,默認是中止的
no 則忽略錯誤繼續。
配置文件中 rdbchecksum
default: yes
在寫入文件和讀取文件時是否開啓rdb文件檢查,檢查是否有無損壞,若是在啓動是檢查發現損壞,則中止啓動。
配置文件中 save
default: yes
save second changes # 查看默認的配置 config get save "900 1 300 10 60 10000" # 900秒內 1次鍵更新了就觸發持久化 或 300秒內 10次更新 持久化 60 秒內 10000次更新 觸發持久化 # 該持久化是 bgsave
手動執行 save
或 bgsave
如下幾種種狀況下會觸發執行快照操做,而且默認的使用bgsave
主從複製時,從庫全量複製同步主庫數據,此時主庫會執行bgsave
命令進行快照;
客戶端執行數據庫清空命令FLUSHALL
時候,觸發快照;
客戶端執行shutdown
關閉redis時,觸發快照,也能夠 使用 nosave
參數顯式聲明不保存快照
shutdown nosave
當redis意外崩潰或者關閉再次啓動時,此時AOF持久化未開啓時(默認未開啓),將使用RDB快照文件恢復數據。
# 查看日誌 cat /var/log/redis/redis-server.log 30448:M 04 Oct 2019 10:09:37.145 # Server initialized 30448:M 04 Oct 2019 10:09:37.145 * DB loaded from disk: 0.000 seconds # 從快照恢復 30448:M 04 Oct 2019 10:09:37.146 * Ready to accept connections
RDB方式不管是執行指令仍是利用配置,沒法作到實時持久化,具體較大的可能性丟失數據
bgsave指令每次運行要執行fork操做建立子進程,要犧牲掉一些性能
Redis的衆多版本中未進行RDB文件格式的版本統一,有可能出現個版本服務之間數據格式沒法兼容現象
存儲數據量較大,效率較低——基於快照思想,每次讀寫都是所有數據,當數據量巨大時,效率很是低
大數據量下的IO性能較低
日誌形式的AOF,將命令追加到文件。AOF能夠將Redis執行的每一條寫命令追加到磁盤文件(appendonly.aof
)中,在redis啓動時候優先選擇從AOF文件恢復數據。由於要頻繁的將每個操做記錄到文件中,因此開啓AOF持久化會對性能有必定的影響,可是大部分狀況下這個影響是能夠接受的。
與RDB持久化相比,AOF持久化數據丟失更少,其消耗內存更少(RDB方式執行bgsve會有內存拷貝)。
redisAOF持久化過程可分爲如下階段:
redis將每一條寫命令以redis通信協議添加至緩衝區aof_buf,這樣的好處在於在大量寫請求狀況下,採用緩衝區暫存一部分命令隨後根據策略一次性寫入磁盤,這樣能夠減小磁盤的I/O次數,提升性能。
當寫命令寫入aof_buf緩衝區後,redis會將緩衝區的命令寫入到文件,redis提供了三種同步策略,由配置參數appendfsync
決定,下面是每一個策略所對應的含義:
no
不使用fsync方法同步,而是交給操做系統write函數去執行同步操做,在linux操做系統中大約每30秒執行一次 sync
(man 2 sync 查看)。這種狀況下,緩衝區數據同步不可控,而且在大量的寫操做下,aof_buf緩衝區會堆積會愈來愈嚴重,一旦redis出現故障,數據丟失嚴重,總體不可控。
always
表示每次有寫操做都調用fsync方法強制內核將數據寫入到aof文件。這種狀況下因爲每次寫命令都寫到了文件中, 雖然數據比較安全,可是由於每次寫操做都會同步到AOF文件中,因此在性能上會有影響,同時因爲頻繁的IO操做,硬盤的使用壽命會下降。
everysec
數據將使用調用操做系統write寫入文件,並使用fsync每秒一次從內核刷新到磁盤。 這是折中的方案,兼顧性能和數據安全,因此redis默認推薦使用該配置。
當開啓AOF時,隨着時間推移,AOF文件會愈來愈大,redis提出一種重寫的策略來緩解數據存儲和恢復壓力。
重複或無效的命令不寫入文件
過時的數據再也不寫入文件
多條命令合併寫入(當多個命令能合併一條命令時候會對其優化合並做爲一個命令寫入,例如「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_current_size
:記錄當前AOF文件大小
aof_rewrite_base_size
:記錄最後一次AOF重寫以後,AOF文件大小
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是阻塞的,如下圖文說明其重寫過程:
開始bgrewriteaof
,判斷當前有沒有bgsave
命令(RDB持久化)/bgrewriteaof
在執行,假若有,則這些命令執行完成之後在執行。
主進程fork出子進程,在這一個短暫的時間內,redis是阻塞的。
當完成重寫後,將重寫後的aof 文件合併到原有aof緩存文件中。並刪除臨時建立的重寫後的aof文件
AOF實現本質是基於redis通信協議,將命令以純文本的方式寫入到文件中。
redis協議:
首先Redis是以行來劃分,每行以\r\n行結束。每一行都有一個消息頭,消息頭共分爲5種分別以下:
(+)
表示一個正確的狀態信息,具體信息是當前行+後面的字符。
(-)
表示一個錯誤信息,具體信息是當前行-後面的字符。
(*)
表示消息體總共有多少行,不包括當前行,*後面是具體的行數。
($)
表示下一行數據長度,不包括換行符長度\r\n,$後面則是對應的長度的數據。
(:)
表示返回一個數值,:後面是相應的數字節符。
咱們能夠直接查看AOF文件中的格式,以下圖:
以前已經提到當AOF開啓時候,redis數據恢復優先選用AOF進行數據恢復,如下使用中止redis來模擬redis故障,而後在重寫啓動進行恢復。
AOF文件最小重寫大小,只有當AOF文件大小大於該值時候纔可能重寫,4.0默認配置64mb。
當前AOF文件大小和最後一次重寫後的大小之間的比率等於或者等於指定的增加百分比,如100表明當前AOF文件是上次重寫的兩倍時候才重寫。默認 100
上文中提到的三種策略,默認 everysec
always | everysec | no
當redis忽然運行崩潰時,會出現aof文件被截斷的狀況,Redis能夠在發生這種狀況時退出並加載錯誤,如下選項控制此行爲。
若是aof-load-truncated設置爲yes,則加載截斷的AOF文件,Redis服務器啓動發出日誌以通知用戶該事件。
若是該選項設置爲no,則服務將停止並顯示錯誤並中止啓動。當該選項設置爲no時,用戶須要在重啓以前使用redis-check-aof
實用程序修復AOF文件在進行啓動。
yes開啓AOF,no關閉AOF 默認 no
指定AOF文件名,4.0沒法經過config set 設置,只能經過修改配置文件設置。默認 appendonly.aof
redis4.0添加了新的持久化方式混合持久化
。
混合持久化默認是關閉的,它採用一種rdb
+ aof
的方式來實現,文件頭rdb
一個全量的快照,格式爲二進制,後面是 aof
格式。這樣恢復會先查看開頭是否爲REDIS
,rdb開頭必然是REDIS
。而後從快照恢復,以後從aof
恢復。
這樣作的好處是能夠結合 rdb 和 aof 的優勢, 快速加載同時避免丟失過多的數據
缺點是 aof 裏面的 rdb 部分就是壓縮格式再也不是 aof 格式,可讀性差。
5 版本的redis 默認的開啓了aof-use-rdb-preamble
可是 appendonly
默認是 no
也就是說,只要開啓了aof 默認的會使用混合持久化。若是要使用單純的aof
則須要手動的 將 aof-use-rdb-preamble
設爲 no
(好坑)
4.0版本的混合持久化默認關閉的,經過aof-use-rdb-preamble
配置參數控制,yes則表示開啓,no表示禁用,默認是禁用的,可經過config set修改。
建立子進程
生成全量的rdb快照,放在appendonly.aof 文件頭部。而後,接下來將aof緩衝區的增量命令以aof方式寫入文件尾
每次恢復數據時,首先從RDB部分恢復,而後執行aof。
開啓了混合持久化時,啓動redis依然優先加載aof文件,aof文件加載可能有兩種狀況以下:
aof文件開頭是rdb的格式, 先加載 rdb內容再加載剩餘的 aof。
aof文件開頭不是rdb的格式,直接以aof格式加載整個文件。
RDB 是一個很是緊湊(compact)的文件,體積小,傳輸速度快,適合災備。
RDB 能夠最大化 Redis 的性能:父進程在保存 RDB 文件時惟一要作的就是 fork
出一個子進程,而後這個子進程就會處理接下來的全部保存工做,父進程無須執行任何磁盤 I/O 操做。
RDB 在恢復大數據集時的速度比 AOF 的恢復速度要快不少。
RDB 丟數據將會丟掉兩次持久化之間的全部數據~
當redis中數據集比較大時候,RDB因爲RDB方式須要對數據進行完成拷貝並生成快照文件,fork的子進程會耗CPU,而且數據越大,RDB快照生成會越耗時。
RDB文件是特定的格式,閱讀性差,因爲格式固定,而且多版本之間存在不兼容狀況。很難受~
數據更完整,秒級數據丟失(取決於設置fsync策略)
兼容性較高,因爲是基於redis通信協議而造成的命令追加方式,不管何種版本的redis都兼容,再者aof文件是明文的,可閱讀性較好。
數據文件體積較大,即便有重寫機制,可是在相同的數據集狀況下,AOF文件一般比RDB文件大。
相對RDB方式,AOF速度慢於RDB,而且在數據量大時候,恢復速度AOF速度也是慢於RDB。
因爲頻繁地將命令同步到文件中,AOF持久化對性能的影響相對RDB較大,可是對於咱們來講是能夠接受的。
混合持久化結合了RDB持久化 和 AOF 持久化的優勢, 因爲絕大部分都是RDB格式,加載速度快,同時結合AOF,增量的數據以AOF方式保存了,數據更少的丟失。
因爲前部分是RDB格式,閱讀性較差,兼容性差,一旦開啓了混合持久化,4.0 版本以前的redis 都不認識這種aof文件~ 。