跟我一塊兒學Redis之Redis持久化必知必會

前言

Redis是出了名的速度快,那是由於在內存中進行數據存儲和操做;若是僅僅是在內存中進行數據存儲,那就會致使如下問題:linux

  • 數據隨進程退出而消失:當服務器斷電或Redis Server進程退出時,內存確定隨之釋放,最後數據也會丟失;可能有些小夥伴認爲只是做爲緩存,數據沒有了,從新從數據庫中讀取放在裏面便可,試想,若是是高併發場景,數據庫豈不是壓力很大;
  • 重要數據沒法恢復:數據丟失以後沒法進行恢復,對於一些重要的數據,只是存在Redis中,而沒有存在關係型數據庫,若是數據丟失便不可恢復;好比刷禮品排行榜,若是數據丟失,用戶確定不肯意的;

對於Redis持久化在工做中和麪試過程當中是一個很重要的技術點,必用必考,接下來詳細說說Redis持久化;面試

正文

Redis針對數據持久化有兩種方案,以下:redis

  • RDB(Redis DataBase):快照形式,即指定時間間隔將Redis內存中的快照數據保存在物理磁盤上,數據保存在*.rdb文件中,以二進制的形式進行存儲,恢復數據直接加載便可;
  • AOF(Append Only File):日誌形式,即將每條寫命令以append-only模式記錄在*.aof文件中,不能修改文件,只能進行追加;後續恢復數據自動執行日誌文件中的命令便可恢復數據;
  • 混合就是RDB和AOF的結合;

兩種方式均可以經過配置文件輕鬆搞定,來,我們先從RDB開始;算法

fork:後續會頻繁提到,簡單解釋一下,fork的做用是複製一個與當前進程同樣的子進程,該子進程的全部數據都和原進程一致。數據庫

RDB持久化

理論放到後面再說,先來看看實際操做,再來作總結;上次對配置文件簡單進行說明,此次就直接找到快照那配置就行啦,先看看默認配置:windows

1

經過 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的值修改了就進行持久化到磁盤,以下:安全

  1. 先將原有的dump.rdb文件刪除掉,避免影響測試效果;服務器

  2. 修改配置文件以下:併發

    image-20201202124046958

  3. 用修改以後,指定該配置文件重啓redis-server,而後開始測試;

    image-20201202125318782

  4. 嘗試打開dump.rdb看看,咋一看是看不懂,但實際上是有對應關係的,這裏就不深究了

    image-20201202181142589

Redis強大吧,不知不覺的就把數據備份,主要是還不影響正常操做,上圖中第四步中就有體現,主進程fork了子進程進行備份,主進程不參與備份持久化操做。既然備份文件有了,如何進行恢復數據呢? redis-server在啓動的時候自動將當前目錄中的備份文件(dump.rdb)數據加載到內存中;以下圖所示:

image-20201202140710879

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,以下:

image-20201202150850388

如何中止或禁用RDB快照自動備份

能夠經過配置文件的形式配置,也能夠經過命令的形式進行關閉,但經過命令的方式,服務器重啓以後就失效了,因此通常建議經過配置文件進行配置;

  • 配置文件方式:去除全部關於save的配置,或者配置一個save ""便可,重啓redis-server;
  • 命令方式:在客戶端中執行config set save ""便可,但redis-server重啓時就恢復默認值了;
RDB備份流程

image-20201202164228149

簡要說明:

  1. 當觸發bgsave持久化時(知足配置條件或手動執行bgsave命令),主進程fork一個子進程進行持久化操做,主進程不參與任何持久化IO操做;

  2. 爲了避免影響原有rdb文件的使用,子進程會將快照數據先寫入到臨時文件;

  3. 當快照數據徹底備份到臨時文件時,就替換掉原有的rdb文件,從而獲得最新數據的rdb文件;

    注:當執行sava命令的時候,會致使阻塞,只有等快照數據持久化完成以後,才能作其餘事情;

RDB持久化優缺點

每一項技術在解決已有問題的時候,確定也會帶來新問題,RDB用來解決持久化問題,那它有什麼優缺點呢?

優勢

  • RDB保存的數據文件比較緊湊,對比AOF來講,相同數據的文件大小比較小;

  • 大量數據持久化時速度相對AOF比較快;

  • RDB中bgsave模式對主進程影響比較小,只有在主進程fork子進程的時候耗費資源,但影響不大;自動備份後臺用的就是bgsave模式;

缺點

  • RDB可能會丟失最後一次沒有備份的數據,若是在最後一次沒開始備份以前,服務器掛了,那最後一次的數據就沒了;
  • 當數據量巨大時,主進程在fork子進程的時候,可能會致使稍微的卡頓;

AOF持久化

既然已經有了RDB持久化了,那爲何還得出一個AOF呢?從RDB的缺點來看,很大程度上是由於可能會丟失最後一次備份以前的數據,對於一些重要數據來講,是不能接受的。而AOF的出現,將數據丟失風險極大的下降。先不說那麼多,實操一把再慢慢聊。

AOF默認狀況是沒開啓的,打開配置文件,爲了避免讓RDB備份影響,這裏暫時先將RDB備份禁用掉,以下:

  1. 禁用RDB備份:

image-20201202175142028

  1. 開啓AOF備份:根據上一篇文章提到的,先找到APPEND ONLY MODE配置塊,將AOF備份開啓appendonly yes

    image-20201202175511758

  2. 配置好了,指定配置文件重啓redis-server,先來看看效果:

    當一啓動redis-server的時候,appendonly.aof文件就已經生成了;來,我們接着敲點命令,以下↓↓↓

    image-20201202182017360

  3. 嘗試打開appendonly.aof文件看看,和dump.rdp文件有什麼不一樣;

    image-20201202182417350
    appendonly.aof只記錄寫命令,讀命令不記錄,並且記錄方式是以追加的方式,因此速度相對比較快;

同RDB同樣,在redis-server重啓時,自動加載AOF文件命令依次執行,最終將數據進行恢復

AOF其餘配置項

這就是Redis的強大,針對每個功能均可以經過配置項進行完成,使用很是方便;

  • appendonly:默認no,不開啓AOF持久化;能夠經過設置爲yes開啓;
  • appendfilename:默認appendonly.aof,表明生成的AOF日誌文件名,能夠更改;
  • appendfsync:默認everysec,設置同步命令到磁盤的策略,即默認每秒經過fsync進行一次命令同步到磁盤;有三種命令同步策略能夠選擇,以下:
    1. always:只要有寫入命令就經過fsync同步到磁盤,數據完整性好,但效率很差;
    2. everysec:每秒經過fsync進行一次命令同步到磁盤,可能會致使一秒中數據的丟失,由於可能在命令還沒同步的時候,機器掛掉等操做,但可接受;綜合考慮,推薦使用這種策略;
    3. 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文件中是沒有必要的,以下圖所示:

image-20201202233318616

上圖中屢次對a1這個Key進行屢次寫入,最終的值爲10,可見若是AOF文件中只記錄一條最終值的寫命令豈不是最好,從而減小AOF文件的大小;這裏文件大小確定達不到自動觸發重寫的條件,這裏就手動觸發,而後再看看AOF文件內容,是否進行了優化,以下:

image-20201202234007490

如上圖可見,重寫以後的AOF文件的確是咱們本身想要,是否是以爲Redis更加牛X了;觸發重寫有如下兩種方式:

  • 自動觸發:即當知足設置的auto-aof-rewrite-percentageauto-aof-rewrite-min-size值會自動觸發重寫;
  • 手動觸發:在客戶端中執行bgrewriteaof命令;
AOF重寫流程

image-20201203000648231

簡要說明:

  1. 當觸發到重寫AOF文件時,主進程fork一個子進程,子進程根據內存中的現有數據進行命令精簡化,重寫到新的AOF文件中;
  2. 在子進程正在重寫AOF文件時,若是有新的寫命令,將其存放到重寫緩衝區,同時也同步到原來的AOF文件;
  3. 當子進程重寫完成以後,通知主進程將重寫緩衝區中的新命令寫入到新AOF文件中,完成以後,用新的AOF文件將原來的AOF文件替換;
  4. 最後獲得優化以後的AOF文件,減小文件大小;
AOF文件修復

對於AOF文件內容的合法性怎麼解決呢,有可能因爲忽然事件,好比宕機,致使AOF文件寫入不完整;也有可能有人惡意添加不規範數據,redis會怎麼處理呢?這裏就模擬手動修改AOF文件,以下:

image-20201203093037933

根據提示,使用redis-check-aof --fix <filename>進行修復,以下:

image-20201203110008592

啓動圖就不截了,小夥伴們試試去;還有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的主從複製;

一個被程序搞醜的帥小夥,關注"Code綜藝圈",跟我一塊兒學~~~

相關文章
相關標籤/搜索