Redis筆記(一)-Redis持久化
Redis持久化
1、故障發生的時候會怎麼樣
2、如何應對故障的發生
redis的持久化,RDB,AOF,區別、工作機制,各自的特點是什麼,適合什麼場景。如何抉擇
redis的企業級的持久化方案是什麼,是用來跟哪些企業級的場景結合起來使用的???
如果想redis僅作為純記憶體的快取來用,可禁止RDB和AOF所有的持久化機制
Redis持久化的作用:
Redis所有的資料都儲存在記憶體中,對資料的更新將非同步地儲存在磁碟上
Redis持久化與高可能有很大關係。
Redis持久化的意義:
在於資料備份和故障恢復。持久化主要是做災難恢復,資料恢復
部署一個redis作為cache快取,或儲存一些較為重要的資料
如果沒有持久化,redis遇到災難性故障時,由於redis資料儲存在記憶體中,就會丟失所有的資料
如果通過持久化將資料搞一份兒在磁碟上去,然後定期比如說同步和備份到一些雲端儲存服務上去,就可以保證資料不丟失全部,還是可以恢復一部分資料回來的。
對於企業級的redis架構來說,持久化是不可減少的
企業級redis叢集架構:海量資料、高併發、高可用
Redis持久化的重要性-快取雪崩
如redis不可用了,要做的事是讓redis儘快變得可用,重啟redis,儘快讓它對外提供服務,
如果沒做資料備份,這時redis啟動了也不可用,因為資料都沒了。
有可能大量的請求過來,快取全部無法命中,在redis裡找不到資料,這時快取雪崩問題,所有請求,沒有在redis命中,就會去mysql資料庫這種資料來源頭中去找,一下子mysql承接高併發,然後就掛了。
mysql掛掉,資料也就無法恢復到redis裡面去。redis的資料從mysql來。。。
如果把redis的持久化做好,備份和恢復方案做到企業級的程度,即使redis故障了,也可通過備份資料,快速恢復,一旦恢復立即對外提供服務。
快取雪崩解決方案:
具體的完整的快取雪崩的場景,還有企業級的解決方案,到後面講
Redis持久化和高可用是有關係的。企業級redis架構中去講解
持久化的方式:
- 快照(先把資料拷貝出來,做個備份):Mysql Dump 和 Redis RDB
- 日誌(某時某點的日誌記錄):MySQL Binlog和Hbase HLog和Redis AOF
PDB(快照)和AOF(日誌)
RDB和AOF兩種持久化機制的工作原理:
AOF日誌會越來越大。
Redis通過rewrite的機制,讓AOF檔案不至於太龐大。就是大概是資料量多的時候,重寫一個新的,把不需要的剔除。
RDB和AOF兩種持久化機制的介紹:
RDB持久化機制:對redis中的資料執行週期性的持久化
AOF持久化機制:對每條寫入命令作為日誌,以append-only的模式寫入一個日誌檔案中,在redis重啟時,可通過回放AOF日誌中的寫入指令來重新構建整個資料集
RDB或AOF都可將redis記憶體中的資料給持久化到磁碟上面來,然後可將這些資料備份到雲伺服器,如阿里雲。
如果redis掛了,伺服器上的記憶體和磁碟上的資料都丟了,可從雲服務上拷貝回來之前的資料,放到指定的目錄中,然後重新啟動redis,redis就會自動根據持久化資料檔案中的資料,去恢復記憶體中的資料,繼續對外提供服務。
注:如果同時用RDB和AOF兩種持久化機制,在redis重啟時,會用AOF來重新構建資料,因AOF中的資料更加完整
1、RDB(快照)持久化機制
1)工作流程
(1)redis根據配置嘗試去生成rdb快照檔案
(2)fork一個子程序出來
(3)子程序嘗試將資料dump到臨時的rdb快照檔案中
(4)完成rdb快照檔案的生成之後,就替換之前的舊的快照檔案
只有一個dump.rdb(二進位制檔案,可以直接載入),每次生成一個新的快照,會覆蓋之前的老快照
2)優點:
(1)適合做冷備:RDB會生成多個數據檔案,每個資料檔案都代表了某一時刻中redis的資料,這種多個數據檔案的方式,適合做冷備,可以將這種完整的資料檔案傳送到一些遠端的安全儲存上去,如Amazon的S3雲服務,阿里雲的ODPS分散式儲存上,以預定好的備份策略來定期備份redis中的資料
關於冷備:
RDB可以做冷備,生成多個檔案,每個檔案都代表了某一個時刻的完整的資料快照
AOF也可以做冷備,只有一個檔案,但是可以每隔一定時間去copy一份這個檔案出來
RDB做冷備,優勢在由redis去控制固定時長生成快照檔案的事情,比較方便; ,在最壞的情況下,提供資料恢復的時候,速度比AOF快
AOF還需自己寫一些指令碼去做這個事情,各種定時。
(2)RDB對redis對外提供的讀寫服務,影響小,可讓redis保持高效能,因為redis主程序只需要fork一個子程序,讓子程序執行磁碟IO操作來進行RDB持久化即可
RDB,每次寫,都是直接寫redis記憶體,只是在一定時,才會將資料寫入磁碟中
AOF,每次都是要寫檔案的,雖然可以快速寫入os cache中,但還是有一定的時間開銷,速度肯定比RDB略慢一些
(3)相對於AOF持久化機制來說,直接基於RDB資料檔案來重啟和恢復redis程序,更加快速
AOF存放的指令日誌,做資料恢復時,要回放和執行所有的指令日誌來恢復出來記憶體中的所有資料
RDB,就是一份資料檔案,恢復的時候,直接載入到記憶體中即可
結合上述優點,RDB特別適合做冷備份
3)缺點:
(1)丟失資料多:如果想在redis故障時,儘可能少的丟失資料,不及AOF。一般RDB資料快照檔案是每隔5分鐘,或更長時間生成一次,一旦redis程序宕機,會丟失最近5分鐘的資料。丟失的資料可能比較多。
所以RDB不適合做第一優先的恢復方案,所以預設是採用AOF進行第一優先恢復。
(2)RDB每次在fork子程序來執行RDB快照資料檔案生成的時候,如果資料檔案特別大,可能導致對客戶端提供的服務暫停數毫秒,或者甚至數秒。
一般不要讓RDB的間隔太長,否則每次生成的RDB檔案太大,對redis本身的效能可能會有影響的
耗時、耗效能(大量消耗效能)。不可控、丟失資料(如果save過程中中途宕機,其他的資料就會丟失,即使是定時策略,也存在這種問題,因為無法保證什麼時候宕機)。
4)配置RDB持久化:
redis.conf檔案,也就是/etc/redis/6379.conf,去配置持久化
save 60 1000
每隔60s,如果超過1000個key發生了變更,就生成一個新的dump.rdb檔案,當前redis記憶體中完整的資料快照,這個操作也被稱之為snapshotting,快照
也可手動呼叫save或bgsave命令,同步或非同步執行rdb快照生成
save可以設定多個,就是多個snapshotting檢查點,每到一個檢查點,就會去check一下,是否有指定的key數量發生了變更,如果有,就生成一個新的dump.rdb檔案
5)生成RDB檔案的三種觸發方式:
Save(同步)、bgsave(非同步)、自動
(1)save命令:複雜度:O(N)、不同步
檔案策略:如果存在老的RDB檔案,新的替換老的
(2)bgsave命令:檔案策略和複雜度與save相同
兩種方式比較:
(3)配置檔案配置的方式:配置檔案配置save seconds changes。但是這樣無法控制save頻率。
最佳配置:
6)基於RDB持久化機制的資料恢復實驗
(1)在redis中儲存幾條資料,立即停掉redis程序,然後重啟redis,看看剛才插入的資料還在不在?
資料還在,為什麼?
因為通過redis-cli SHUTDOWN這種方式去停掉redis是一種安全退出的模式,redis在退出的時候會將記憶體中的資料立即生成一份完整的rdb快照
/var/redis/6379/dump.rdb
(2)在redis中再儲存幾條新的資料,用kill -9粗暴殺死redis程序,模擬redis故障異常退出,導致記憶體資料丟失的場景。redis程序異常被殺掉,資料沒有進dump檔案,幾條最新的資料就丟失了
(2)手動設定一個save檢查點,save 5 1 5秒鐘一次snapshotting
(3)寫入幾條資料,等待5秒鐘,會發現自動進行了一次dump rdb快照,在dump.rdb中發現了資料
(4)異常停掉redis程序,再重新啟動redis,看剛才插入的資料還在
rdb的手動配置檢查點,以及rdb快照的生成,包括資料的丟失和恢復
7)總結
1. RDB是Redis記憶體到硬碟的快照,用於持久化。
2. save通常會阻塞Redis。影響其他客戶端連線時間。
3. bgsave不會阻塞Redis ,但是會fork新程序。
4. save自動配置滿足任一就會被執行。
5. 有些觸發機制不容忽視
2、AOF(日誌)持久化機制
以日誌的形式來記錄每個寫操作(讀操作不記錄),將Redis執行過的所有寫指令記錄下來(讀操作不記錄),只許追加檔案但不可以改寫檔案,redis啟動之初會讀取該檔案重新構建資料,換言之,redis重啟的話就根據日誌檔案的內容將寫指令從前到後執行一次以完成資料的恢復工作
• 開啟:預設AOF沒有開啟:appendonly no #如果要開啟,改為yes
注意的是啟動的目錄和儲存aof檔案目錄是否一致
• 修復:使用redis-check-aof –fix 進行修復
• 恢復:重啟redis然後重新載入
5)AOF破損檔案的修復
如果redis在append資料到AOF檔案時,機器宕機了,可能會導致AOF檔案破損
用redis-check-aof --fix命令來修復破損的AOF檔案
AOF預設名稱:appendonlyfilename appendonly.aof
1)AOF工作原理與rewrite重寫機制
工作原理:
(1)redis fork一個子程序
(2)子程序基於當前記憶體中的資料,構建日誌,開始往一個新的臨時的AOF檔案中寫入日誌
(3)redis主程序,接收到client新的寫操作之後,在記憶體中寫入日誌,同時新的日誌也繼續寫入舊的AOF檔案
(4)子程序寫完新的日誌檔案之後,redis主程序將記憶體中的新日誌再次追加到新的AOF檔案中
(5)用新的日誌檔案替換掉舊的日誌檔案
重寫機制:把過期的,重複的,沒有用的,都丟掉,只留了有用的。減少磁碟的佔用量,加速恢復速度。
AOF採用檔案追加方式,檔案會越來越大為避免出現此種情況,新增了重寫機制,當AOF檔案的大小超過所設定的閾值時,Redis就會啟動AOF檔案的內容壓縮,只保留可以恢復資料的最小指令集.可以使用命令bgrewriteaof
AOF檔案持續增長而過大時,會fork出一條新程序來將檔案重寫(也是先寫臨時檔案最後再rename),
遍歷新程序的記憶體中資料,每條記錄有一條的Set語句。重寫aof檔案的操作,並沒有讀取舊的aof檔案,
而是將整個記憶體中的資料庫內容用命令的方式重寫了一個新的aof檔案,這點和快照有點類似
Rewrite觸發機制:
Redis會記錄上次重寫時的AOF大小,預設配置是當AOF檔案大小是上次rewrite後大小的一倍且檔案大於64M時觸發。預設64M。
AOF日誌膨脹:
redis中的資料有限,很多資料或自動過期,或被使用者刪除,或被redis用快取清除的演算法清理掉。
redis中的資料會不斷淘汰掉舊的,就一部分常用的資料會被自動保留在redis記憶體中
所以可能很多之前的已經被清理掉的資料,對應的寫日誌還停留在AOF中,AOF日誌檔案就一個,會不斷的膨脹
解決方案-rewrite:
AOF會自動在後臺每隔一定時間做rewrite操作,如日誌裡已存放針對100w資料的寫日誌; redis記憶體只剩下10萬; 基於記憶體中當前的10萬資料構建一套最新的日誌,到AOF中; 覆蓋之前的老日誌; 確保AOF日誌檔案不會過大,保持跟redis記憶體資料量一致
redis 2.4之前,需要手動開發一些指令碼,crontab,通過BGREWRITEAOF命令去執行AOF rewrite,
redis 2.4之後,會自動進行rewrite操作
在redis.conf中,可以配置rewrite策略:
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
比如說上一次AOF rewrite之後,是128mb、然後就會接著128mb繼續寫AOF的日誌,如果發現增長的比例,超過了之前的100%,256mb,就可能會去觸發一次rewrite。但是還要去跟min-size,64mb去比較,256mb > 64mb,才會去觸發rewrite。
2)優點:
(1)資料丟失少:AOF可更好的保護資料不丟失,一般AOF會每隔1秒,通過一個後臺執行緒執行一次fsync操作,保證os cache中的資料寫入磁碟中,最多丟失1秒鐘的資料
(2)AOF日誌檔案以append-only模式寫入,所以沒有任何磁碟定址的開銷,寫入效能非常高,而且檔案不容易破損,即使檔案尾部破損,也很容易修復(提供了工具)
(3)AOF日誌檔案即使過大的時候,出現後臺重寫操作也不會影響客戶端的讀寫。因為在rewrite log時,會對其中的指導進行壓縮,創建出一份需要恢復資料的最小日誌出來。再建立新日誌檔案的時候,老的日誌檔案還是照常寫入。當新的merge後的日誌檔案ready的時候,再交換新老日誌檔案即可。
(4)AOF日誌檔案的命令通過非常可讀的方式進行記錄,這個特性非常適合做災難性的誤刪除的緊急恢復。如某人不小心用flushall命令清空了所有資料,只要這個時候後臺rewrite還沒有發生,那麼就可以立即拷貝AOF檔案,將最後一條flushall命令給刪了,然後再將該AOF檔案放回去,就可以通過恢復機制,自動恢復所有資料(很少使用到)
3)缺點:
(1)對於同一份資料來說,AOF日誌檔案通常比RDB資料快照檔案更大
(2)AOF開啟後,支援的寫QPS會比RDB支援的寫QPS低,因為AOF一般會配置成每秒fsync一次日誌檔案,當然,每秒一次fsync,效能也還是很高的。
如果要保證一條資料都不丟,可以AOF的fsync設定成每寫入一條資料,fsync一次,但這樣redis的QPS大降
(3)以前AOF發生過bug,就是通過AOF記錄的日誌,進行資料恢復的時候,沒有恢復一模一樣的資料出來。所以說,類似AOF這種較為複雜的基於命令日誌/merge/回放的方式,比基於RDB每次持久化一份完整的資料快照檔案的方式,更加脆弱一些,容易有bug。不過AOF就是為了避免rewrite過程導致的bug,因此每次rewrite並不是基於舊的指令日誌進行merge的,而是基於當時記憶體中的資料進行指令的重新構建,這樣健壯性會好很多。
(4)唯一的比較大的缺點,其實就是做資料恢復的時候,會比較慢,還有做冷備,定期的備份,不太方便,可能要自己手寫複雜的指令碼去做,做冷備不太合適
• 相同資料集的資料而言aof檔案要遠大於rdb檔案,恢復速度慢於rdb
• aof執行效率要慢於rdb,每秒同步策略效率較好,不同步效率和rdb相同
4)AOF持久化的配置
AOF持久化,預設是關閉的,預設是開啟RDB持久化
appendonly yes,開啟AOF持久化機制,在生產環境一般來說AOF都是開啟的,除非允許隨便丟個幾分鐘的資料。
開啟AOF持久化機制後,redis每次接收到一條寫命令,就會寫入日誌檔案中,當然是先寫入os cache的,然後每隔一定時間再fsync一下
即使AOF和RDB都開啟了,redis重啟的時候,也是優先通過AOF進行資料恢復的,因為aof資料比較完整
可以配置AOF的fsync策略,有三種策略,
1.always:每次寫入一條資料就執行一次fsync; 每次寫入一條資料,立即將這個資料對應的寫日誌fsync到磁碟上去,效能非常非常差,吞吐量很低; 確保redis裡的資料一條都不丟
2. everysec(預設): 每隔一秒執行一次fsync; 每秒將os cache中的資料fsync到磁碟,最常用的,生產環境一般都這麼配置,效能很高,QPS還是可以上萬的
3.no: 不主動執行fsync。僅僅redis負責將資料寫入os cache就撒手不管了,後面os自己會時不時有自己的策略將資料刷入磁碟,不可控了
mysql -> 記憶體策略,大量磁碟,QPS到一兩k。QPS,每秒鐘的請求數量
redis -> 記憶體,磁碟持久化,QPS到多少,單機,一般來說,上萬QPS沒問題
5)AOF日誌修改策略(3種):
三種appendfsysnc:同步策略:
• 每修改同步:appendfsync always 同步持久化 每次發生資料變更會被立即記錄到磁碟 效能較差但資料完整性比較好
• 每秒同步:appendfsync everysec(預設)非同步操作,每秒記錄 如果一秒內宕機,有資料丟失
• 不同步:appendfsync no 從不同步
能保證保護硬碟。有可能會丟失資料
6)AOF重寫實現方式(2種):
一種是bgrewriteaof。一種是AOF重寫配置
AOF重寫配置:
多大後需要重寫
觸發時機:
自動觸發時機=
aof_current_size>auto-aof-rewrite-min-size&&(aof_current_size-aof_base_size)/aof_base_size>=auto-aof-rewrite-percentage
7)AOF持久化的資料恢復實驗
(1)先僅僅開啟RDB,寫入一些資料,然後kill -9殺掉redis程序,重啟redis,發現數據沒了,因為RDB快照還沒生成
(2)開啟AOF的開關,啟用AOF持久化
(3)寫入一些資料,觀察AOF檔案中的日誌內容
其實在appendonly.aof檔案中,可以看到剛寫的日誌,它們其實就是先寫入os cache的,然後1秒後才fsync到磁碟中,只有fsync到磁碟中了,才是安全的,要不然光是在os cache中,機器只要重啟,就什麼都沒了
(4)kill -9殺掉redis程序,重新啟動redis程序,發現數據被恢復回來了,就是從AOF檔案中恢復回來的
redis程序啟動的時候,直接就會從appendonly.aof中載入所有的日誌,把記憶體中的資料恢復回來
總結:
• AOF 檔案是一個只進行追加的日誌檔案
• Redis可以在AOF檔案體積變得過大時,自動地在後臺對AOF進行重寫
• AOF檔案有序地儲存了對資料庫執行所有寫入操作,這些寫入操作作為redis協議的格式儲存,因此AOF檔案的內容非常容易被人讀懂,對檔案進行分析也很輕鬆
• 對於相同的資料集來說,AOF檔案的體積通常大於RDB檔案的體積,根據所使用的fsync策略,AOF的速度可能會慢於RDB
3、RDB和AOF如何選擇:
(1)不要僅僅使用RDB,因為會導致丟失很多資料
(2)也不要僅僅使用AOF,因為有兩個問題,
第一,通過AOF做冷備,沒有RDB做冷備,來的恢復速度更快;
第二,RDB每次簡單粗暴生成資料快照,更加健壯,可以避免AOF這種複雜的備份和恢復機制的bug
(3)綜合使用AOF和RDB兩種持久化機制,用AOF來保證資料不丟失,作為資料恢復的第一選擇; 用RDB來做不同程度的冷備,在AOF檔案都丟失或損壞不可用的時候,還可以使用RDB來進行快速的資料恢復
只做快取:如果你只希望你的資料在伺服器執行的時候存在,你也可以不使用任何持久化方式.
同時開啟兩種持久化方式
–在這種情況下,當redis重啟的時候會優先載入AOF檔案來恢復原始的資料, 因為在通常情況下AOF檔案儲存的資料集要比RDB檔案儲存的資料集要完整.
–RDB的資料不實時,同時使用兩者時伺服器重啟也只會找AOF檔案。那要不要只使用AOF呢?
不要,因為RDB更適合用於備份資料庫(AOF在不斷變化不好備份), 快速重啟,而且不會有AOF可能潛在的bug,留著作為一個萬一的手段。
AOF和RDB同時工作
(1)如果RDB在執行snapshotting操作,那麼redis不會執行AOF rewrite; 如果redis再執行AOF rewrite,那麼就不會執行RDB snapshotting
(2)如果RDB在執行snapshotting,此時使用者執行BGREWRITEAOF命令,那麼等RDB快照生成之後,才會去執行AOF rewrite
(3)同時有RDB snapshot檔案和AOF日誌檔案,那麼redis重啟的時候,會優先使用AOF進行資料恢復,因為其中的日誌更完整
Q:同時出現RDB和AOF是衝突呢?還是協作?
協作,不會衝突! 那麼是如何協作,首先載入哪一個檔案呢?
進行測試,生成dump.rdb和appendonly.aof檔案,然後在appendonly.aof使檔案最後隨便加入一些東西,使檔案出錯,然後重新啟動redis服務,發現服務沒有啟動成功!那麼就可以知道首先載入的是aof檔案,使用redis-check-aof 工具修復aof檔案,重新啟動,發現啟動成功!
總結:兩者可以共存,但是首先啟動找的是aof。
當redis伺服器掛掉時,重啟時將按照以下優先順序恢復資料到記憶體:
如果只配置AOF,重啟時載入AOF檔案恢復資料;
如果同時 配置了RBD和AOF,啟動是隻載入AOF檔案恢復資料;
如果只配置RBD,啟動是講載入dump檔案恢復資料。
恢復時需要注意,要是主庫掛了不能直接重啟主庫,否則會直接覆蓋掉從庫的AOF檔案,一定要確保要恢復的檔案都正確才能啟動,否則會沖掉原來的檔案。
如何修復:redis-check-aof –fix appendonly.aof
持久化恢復:
檢視日誌
看到有臨時子程序
一段時間後就沒了子程序