前言
Redis是出了名的速度快,那是因為在記憶體中進行資料儲存和操作;如果僅僅是在記憶體中進行資料儲存,那就會導致以下問題:
資料隨程序退出而消失:當伺服器斷電或Redis Server程序退出時,記憶體肯定隨之釋放,最後資料也會丟失;可能有些小夥伴認為只是作為快取,資料沒有了,重新從資料庫中讀取放在裡面即可,試想,如果是高併發場景,資料庫豈不是壓力很大;重要資料無法恢復:資料丟失之後無法進行恢復,對於一些重要的資料,只是存在Redis中,而沒有存在關係型資料庫,如果資料丟失便不可恢復;比如刷禮品排行榜,如果資料丟失,使用者肯定不願意的;對於Redis持久化在工作中和麵試過程中是一個很重要的技術點,必用必考,接下來詳細說說Redis持久化;
正文
Redis針對資料持久化有兩種方案,如下:
RDB(Redis DataBase):快照形式,即指定時間間隔將Redis記憶體中的快照資料儲存在物理磁碟上,資料儲存在*.rdb檔案中,以二進位制的形式進行儲存,恢復資料直接載入即可;AOF(Append Only File):日誌形式,即將每條寫命令以append-only模式記錄在*.aof檔案中,不能修改檔案,只能進行追加;後續恢復資料自動執行日誌檔案中的命令即可恢復資料;混合就是RDB和AOF的結合;兩種方式都可以透過配置檔案輕鬆搞定,來,咱們先從RDB開始;
fork:後續會頻繁提到,簡單解釋一下,fork的作用是複製一個與當前程序一樣的子程序,該子程序的所有資料都和原程序一致。
RDB持久化
理論放到後面再說,先來看看實際操作,再來做總結;上次對配置檔案簡單進行說明,這次就直接找到快照那配置就行啦,先看看預設配置:
透過 save <seconds> <changes>進行條件配置,如果觸發條件就自動進行RDB持久化操作。預設配置中包含以下三種條件,滿足其中一個就自動儲存資料到磁碟:
save 900 1:900秒內(15分鐘)至少有1個key的值進行修改;save 300 10:300秒內(五分鐘)至少有10個key的值進行修改;save 60 10000:900秒內(1分鐘)至少有10000個key的值進行修改;測試驗證
為了測試時間方便,將其中一個條件改為1分鐘內有3個key的值修改了就進行持久化到磁碟,如下:
2.修改配置檔案如下:
3.用修改之後,指定該配置檔案重啟redis-server,然後開始測試;
4.嘗試開啟dump.rdb看看,咋一看是看不懂,但其實是有對應關係的,這裡就不深究了
Redis強大吧,不知不覺的就把資料備份,主要是還不影響正常操作,上圖中第四步中就有體現,主程序fork了子程序進行備份,主程序不參與備份持久化操作。既然備份檔案有了,如何進行恢復資料呢? redis-server在啟動的時候自動將當前目錄中的備份檔案(dump.rdb)資料載入到記憶體中;如下圖所示:
RDB其他配置項
那為什麼是dump.rdb檔案?,為什麼又是當前目錄?,如果rdb備份檔案寫入失敗了怎麼辦?這些透過配置檔案中SNAPSHOTTING部分都有詳細的說明,並提供相關配置項進行設定,如下:
stop-writes-on-bgsave-error:預設設定為yes,即當RDB備份資料失敗時,Redis會停止接收資料,保證資料的一致性;如果對資料一致性要求不高的,可以將其進行關閉,設定為no,但推薦都開啟;rdbcompression:預設設定為yes,開啟壓縮之後會採用LZF演算法對備份檔案dump.rdb進行壓縮,但會消耗點CPU效能進行處理,但影響並不大,推薦都開啟;rdbchecksum:預設設定為yes,即開啟之後會對備份檔案資料進行校驗,但會消耗CPU效能,如果追求效能提高可以將其關閉,但影響也不大,推薦都開啟;dbfilename:預設為dump.rdb,即預設的備份檔名為dump.rdb,可以透過這個配置進行修改;dir:預設為當前目錄,即備份的檔案存放的目錄。RDB手動觸發備份
上面說到自動觸發備份,其實在實際應用場景中,有些需求很急,如果要求等到滿足條件備份完成之後才處理問題,間隔時間短還好點,如果間隔時間超過5分鐘,估計等待處理問題的人要上房揭瓦啦;Redis同樣為大家考慮到了,提供手動備份的方式,如下:
save:直接執行save命令,但會阻塞主程序操作,只能等待備份完成之後才能進行其他處理;bgsave:直接執行bgsave命令,主程序會fork一個子程序進行備份操作,不阻塞主程序;當資料過大時,可能會在fork的時候有短暫的耗時,但影響不大; 上面的自動備份其實最後也是bgsave這種模式。flushall:執行flushall命令會觸發RBD備份,但是備份檔案是空的,在本地測試一把就行了,沒有任何意義,千萬別在生產庫上用;簡單測試一下,刪除dump.rdb檔案,將配置檔案恢復到預設值,然後指定配置檔案重啟redis-server,如下:
如何停止或禁用RDB快照自動備份
可以透過配置檔案的形式配置,也可以透過命令的形式進行關閉,但透過命令的方式,伺服器重啟之後就失效了,所以一般建議透過配置檔案進行配置;
配置檔案方式:去除所有關於save的配置,或者配置一個save ""即可,重啟redis-server;命令方式:在客戶端中執行config set save ""即可,但redis-server重啟時就恢復預設值了;RDB備份流程
簡要說明:
當觸發bgsave持久化時(滿足配置條件或手動執行bgsave命令),主程序fork一個子程序進行持久化操作,主程序不參與任何持久化IO操作;為了不影響原有rdb檔案的使用,子程序會將快照資料先寫入到臨時檔案;當快照資料完全備份到臨時檔案時,就替換掉原有的rdb檔案,從而得到最新資料的rdb檔案;注:當執行sava命令的時候,會導致阻塞,只有等快照資料持久化完成之後,才能做其他事情;
RDB持久化優缺點
每一項技術在解決已有問題的時候,肯定也會帶來新問題,RDB用來解決持久化問題,那它有什麼優缺點呢?
優點
RDB儲存的資料檔案比較緊湊,對比AOF來說,相同資料的檔案大小比較小;大量資料持久化時速度相對AOF比較快;RDB中bgsave模式對主程序影響比較小,只有在主程序fork子程序的時候耗費資源,但影響不大;自動備份後臺用的就是bgsave模式;缺點
RDB可能會丟失最後一次沒有備份的資料,如果在最後一次沒開始備份之前,伺服器掛了,那最後一次的資料就沒了;當資料量巨大時,主程序在fork子程序的時候,可能會導致稍微的卡頓;AOF持久化
既然已經有了RDB持久化了,那為什麼還得出一個AOF呢?從RDB的缺點來看,很大程度上是因為可能會丟失最後一次備份之前的資料,對於一些重要資料來說,是不能接受的。而AOF的出現,將資料丟失風險極大的降低。先不說那麼多,實操一把再慢慢聊。
AOF預設情況是沒開啟的,開啟配置檔案,為了不讓RDB備份影響,這裡暫時先將RDB備份禁用掉,如下:
1.禁用RDB備份:
2.開啟AOF備份:根據上一篇文章提到的,先找到APPEND ONLY MODE配置塊,將AOF備份開啟appendonly yes
3.配置好了,指定配置檔案重啟redis-server,先來看看效果:
4.嘗試開啟appendonly.aof檔案看看,和dump.rdp檔案有什麼不同;
appendonly.aof只記錄寫命令,讀命令不記錄,而且記錄方式是以追加的方式,所以速度相對比較快;
同RDB一樣,在redis-server重啟時,自動載入AOF檔案命令依次執行,最終將資料進行恢復;
AOF其他配置項
這就是Redis的強大,針對每一個功能都可以透過配置項進行完成,使用非常方便;
appendonly:預設no,不開啟AOF持久化;可以透過設定為yes開啟;appendfilename:預設appendonly.aof,代表生成的AOF日誌檔名,可以更改;appendfsync:預設everysec,設定同步命令到磁碟的策略,即預設每秒透過fsync進行一次命令同步到磁碟;有三種命令同步策略可以選擇,如下:always:只要有寫入命令就透過fsync同步到磁碟,資料完整性好,但效率不好;everysec:每秒透過fsync進行一次命令同步到磁碟,可能會導致一秒中資料的丟失,因為可能在命令還沒同步的時候,機器掛掉等操作,但可接受;綜合考慮,推薦使用這種策略;no:不同步,由作業系統處理,這種資料不能保證安全;auto-aof-rewrite-percentage:預設100,搭配auto-aof-rewrite-min-size一起觸發AOF檔案重寫策略,即預設噹噹前AOF檔案大小是上次重寫的兩倍時才重寫,為了避免比率達到觸發條件,但檔案很小就觸發重寫的情況,所以搭配auto-aof-rewrite-min-size設定AOF檔案的最小重寫大小;即當前AOF檔案大小達到比率的同時檔案大小不低於auto-aof-rewrite-min-size設定的值才觸發重寫;auto-aof-rewrite-min-size:預設64mb,搭配auto-aof-rewrite-percentage使用;AOF觸發重寫
當執行的寫命令過多時,就會導致AOF檔案過度增大,而對於一些重複性的命令存在AOF檔案中是沒有必要的,如下圖所示:
上圖中多次對a1這個Key進行多次寫入,最終的值為10,可見如果AOF檔案中只記錄一條最終值的寫命令豈不是最好,從而減少AOF檔案的大小;這裡檔案大小肯定達不到自動觸發重寫的條件,這裡就手動觸發,然後再看看AOF檔案內容,是否進行了最佳化,如下:
如上圖可見,重寫之後的AOF檔案的確是我們自己想要,是不是覺得Redis更加牛X了;觸發重寫有以下兩種方式:
自動觸發:即當滿足設定的auto-aof-rewrite-percentage和auto-aof-rewrite-min-size值會自動觸發重寫;手動觸發:在客戶端中執行bgrewriteaof命令;AOF重寫流程
簡要說明:
當觸發到重寫AOF檔案時,主程序fork一個子程序,子程序根據記憶體中的現有資料進行命令精簡化,重寫到新的AOF檔案中;在子程序正在重寫AOF檔案時,如果有新的寫命令,將其存放到重寫緩衝區,同時也同步到原來的AOF檔案;當子程序重寫完成之後,通知主程序將重寫緩衝區中的新命令寫入到新AOF檔案中,完成之後,用新的AOF檔案將原來的AOF檔案替換;最後得到最佳化之後的AOF檔案,減少檔案大小;AOF檔案修復
對於AOF檔案內容的合法性怎麼解決呢,有可能由於突然事件,比如宕機,導致AOF檔案寫入不完整;也有可能有人惡意新增不規範資料,redis會怎麼處理呢?這裡就模擬手動修改AOF檔案,如下:
根據提示,使用redis-check-aof --fix <filename>進行修復,如下:
啟動圖就不截了,小夥伴們試試去;還有redis也能對rdb檔案修復,文中沒有體現,但小夥伴記得去嘗試一下,用redis-check-rdb這個工具即可,在windows版本中redis沒有提供此工具,去linux用高點的版本實操一把。
AOF持久化優缺點
AOF的出現,是解決了RDB丟失最後一次沒儲存的資料,極大的降低了資料丟失的風險,但其也帶來相關問題;
優點
降低資料丟失風險,如果丟失,最多一秒資料;以追加方式記錄日誌,速度快;自動最佳化AOF檔案,檔案過大時進行重寫,精簡AOF檔案;缺點
相同大資料,AOF檔案比RDB檔案大,佔用磁碟空間;對於大資料的恢復,速度沒有RDB快;混合持久化
在redis4.0之後,提供了混合持久化配置開啟功能; 混合持久化就是結合RDB和AOF各自優點進行整合的持久化方案,從而解決使用AOF恢復資料較慢的問題;
原理就是在AOF檔案的前半段加入RDB快照資料,後面才是增量資料的命令記錄;在配置檔案中進行配置即可:aof-use-rdb-preamble yes,高版本redis都預設開啟這種混合持久化模式;
優點:解決了單純AOF恢復資料較慢的問題;
缺點:不能相容低版本redis場景;
選擇哪個持久化比較合適?
如果需求對資料完整性要求不是很高,可以接受短時間資料丟失,RDB快照持久化方式是最好不過的選擇;
如果對資料完整性要求比較嚴格,使用AOF日誌形式進行持久化比較合適;
如果redis版本在4.0以上,可以使用混合持久化的方式,降低純AOF檔案的恢復資料的時間;
如果僅僅是快取,快取資料也不重要,併發也不是很高,可以不用開啟持久化;
注: 如果不是使用混合持久化,而是將RDB和AOF同時開啟,redis-server恢復資料的時候會優先使用AOF檔案進行資料恢復,因為AOF檔案相對比較完整;
總結
暫時就到這吧,後續遇到相關問題再來記錄分享;這個知識點比較重要,所以小夥伴們一定要自己嘗試一下哦;使用真的很簡單,進行簡單的配置就完事了,如果能知道其簡單的原理,遇到問題就沒那麼苦惱;下次我們來聊redis的主從複製;
原文連結:https://www.cnblogs.com/zoe-zyq/p/14083918.html