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


前言

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持久化

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

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綜藝圈",跟我一起學~~~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM