redis系列--redis4.0深刻持久化

前言

在以前的博文中已經詳細的介紹了redis4.0基礎部分,而且在memcache和redis對比中說起redis提供可靠的數據持久化方案,而memcache沒有數據持久化方案,本篇博文將詳細介紹redis4.0所提供的持久化方案:RDB持久化和AOF持久化以及redis4.0新特性混合持久化。這裏將從原理到配置以及相關實踐進行說明,但願能對你有所幫助。html

1、RDB持久化

簡介

RDB持久化方式是經過快照(snapshotting)完成的,當符合必定條件時,redis會自動將內存中全部數據以二進制方式生成一份副本並存儲在硬盤上。當redis重啓時,而且AOF持久化未開啓時,redis會讀取RDB持久化生成的二進制文件(默認名稱dump.rdb,可經過設置dbfilename修改)進行數據恢復,對於持久化信息能夠用過命令「info Persistence」查看。linux

快照文件位置

RDB快照文件存儲文件位置由dir配置參數指明,文件名由dbfilename指定,以下:redis

 

快照觸發條件

RDB生成快照可自動促發,也可使用命令手動觸發,如下是redis觸發執行快照條件,後續會對每一個條件詳細說明:數據庫

  1. 客戶端執行命令save和bgsave會生成快照;
  2. 根據配置文件save m n規則進行自動快照;
  3. 主從複製時,從庫全量複製同步主庫數據,此時主庫會執行bgsave命令進行快照;
  4. 客戶端執行數據庫清空命令FLUSHALL時候,觸發快照;
  5. 客戶端執行shutdown關閉redis時,觸發快照;

 

save命令觸發

客戶端執行save命令,該命令強制redis執行快照,這時候redis處於阻塞狀態,不會響應任何其餘客戶端發來的請求,直到RDB快照文件執行完畢,因此請慎用。centos

實踐操做:安全

首先使用info Persistence查看最近一次持久化時間:服務器

此時咱們執行save命令,並再次查看最新快照保存時間已是最新一次時間:app

固然你也能夠直接查看RDB數據文件目錄下的RDB文件最新時間:函數

 

bgsave命令觸發

bgsave命令能夠理解爲background save即:「後臺保存」。當執行bgsave命令時,redis會fork出一個子進程來執行快照生成操做,須要注意的redis是在fork子進程這個簡短的時間redis是阻塞的(此段時間不會響應客戶端請求,),當子進程建立完成之後redis響應客戶端請求。其實redis自動快照也是使用bgsave來完成的。性能

爲了能清楚瞭解bgsave工做過程,如下將圖文詳細描述其工做過程:

對上述過程描述:

  1. 客戶端執行bgsave命令,redis主進程收到指令並判斷此時是否在執行bgrewriteaof(AOF文件從新過程,後續會講解),若是此時正好在執行則bgsave直接返回,不fork子進程,若是沒有執行bgrewriteaof重寫AOF文件,則進入下一個階段;
  2. 主進程調用fork方法建立子進程,在建立過程當中redis主進程阻塞,因此不能響應客戶端請求;
  3. 子進程建立完成之後,bgsave命令返回「Background saving started」,此時標誌着redis能夠響應客戶端請求了;
  4. 子常常根據主進程的內存副本建立臨時快照文件,當快照文件完成之後對原快照文件進行替換;
  5. 子進程發送信號給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文件壓縮,該功能能夠節約磁盤空間

 

 2、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 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演示重寫。

查看日誌:

 

3、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格式數據。

 

4、優缺點 

 RDB

優勢:

  1. RDB 是一個很是緊湊(compact)的文件,體積小,所以在傳輸速度上比較快,所以適合災難恢復。 

  2. RDB 能夠最大化 Redis 的性能:父進程在保存 RDB 文件時惟一要作的就是 fork 出一個子進程,而後這個子進程就會處理接下來的全部保存工做,父進程無須執行任何磁盤 I/O 操做。

  3. RDB 在恢復大數據集時的速度比 AOF 的恢復速度要快。

缺點:

  1. RDB是一個快照過程,沒法完整的保存因此數據,尤爲在數據量比較大時候,一旦出現故障丟失的數據將更多。
  2. 當redis中數據集比較大時候,RDB因爲RDB方式須要對數據進行完成拷貝並生成快照文件,fork的子進程會耗CPU,而且數據越大,RDB快照生成會越耗時。
  3. RDB文件是特定的格式,閱讀性差,因爲格式固定,可能存在不兼容狀況。

AOF 

優勢:

  1. 數據更完整,秒級數據丟失(取決於設置fsync策略)。
  2. 兼容性較高,因爲是基於redis通信協議而造成的命令追加方式,不管何種版本的redis都兼容,再者aof文件是明文的,可閱讀性較好。

缺點:

  1. 數據文件體積較大,即便有重寫機制,可是在相同的數據集狀況下,AOF文件一般比RDB文件大。
  2. 相對RDB方式,AOF速度慢於RDB,而且在數據量大時候,恢復速度AOF速度也是慢於RDB。
  3. 因爲頻繁地將命令同步到文件中,AOF持久化對性能的影響相對RDB較大,可是對於咱們來講是能夠接受的。

混合持久化

優勢:

  1. 混合持久化結合了RDB持久化 和 AOF 持久化的優勢, 因爲絕大部分都是RDB格式,加載速度快,同時結合AOF,增量的數據以AOF方式保存了,數據更少的丟失。

缺點:

  1. 兼容性差,一旦開啓了混合持久化,在4.0以前版本都不識別該aof文件,同時因爲前部分是RDB格式,閱讀性較差

 

5、相關命令

aof文件檢查

redis-check-aof /etc/redis/appendonly.aof

rdb文件檢查

redis-check-rdb /etc/redis/dump.rdb

查看持久化信息

info Persistence

查看狀態信息

info stats

 

以上是全部內容,但願對你有幫助~

相關文章
相關標籤/搜索