七、Redis持久化的兩種方式RDB和AOF理解

前言

前面將了redis的主從複製以及怎麼搭建,還介紹了哨兵模式以及哨兵模式的搭建。雖然操作跟上了,但是還是補一下redis的持久化。redis之所以這麼流行,很大一部分原因便是持久化,斷電重啓數據不消失,使得redis在數據庫領域中站穩了腳。前文將的主從複製其實就是依賴持久化的,如果沒有持久化,這些數據都不會從主服務器備份到從服務器。下文我們就講講redis的持久化。

說起redis持久化,大家或多或少都知道一些,簡單點一句話也能概括。redis通過RDB和AOF方式將數據存入磁盤,實現持久化。RDB是定期生成快照存入磁盤中,AOF是將寫操作存入磁盤中。二者各有優劣,RDB 是存放數據庫中數據,適合做數據備份,但是數據可能不全,最近幾分鐘的數據可能沒有。AOF是每秒中執行一次,如果有寫操作的命令就存儲起來,最多隻會丟失1秒鐘的數據,適合做數據恢復。但是這個就不適合做數據備份了,並且由於每秒都會執行多多少少會搶佔redis的內存,會影響性能。但是在實際應用中是二者是配合使用的。

下面就來具體的講講RDB和AOF吧

RDB

RDB 的全稱是 redis database. 顧名思義,RDB就是將redis數據庫,用來存儲數據的,所以通過RDB方式持久化就是將存在redis內存中的數據寫入到RDB文件中保存到磁盤上從而實現持久化的。
RDB文件是一個壓縮的二進制文件,通過這個文件可以還原redis數據庫的數據,從而達到數據恢復的目的,借用一下《redis設計與實現》講的這張圖,途中數據庫狀態可以理解爲redis內存中存儲的數據。
在這裏插入圖片描述
既然RDB持久化的方式是生成RDB文件,那麼這個RDB文件是怎麼生成的呢?
RDB文件生成的方式有兩種,一種是通過命令手動生成快照,還有一個是通過配置自動生成快照。下面我們來分別看看。

通過save和bgsava命令生成RDB文件

這兩個命令都是可以直接運行的。

save命令,會阻塞服務器進程,只有當RDB文件生成成功纔會接着響應服務端的其他命令。
在這裏插入圖片描述
而bgsave ,既然有這個命令,肯定是和save有所不同的,bgsave 不會阻塞服務器進程,會創建一個子進程來創建RDB文件
在這裏插入圖片描述
但是注意的是使用bgsave命令的時候,雖然是通過子進程生成RDB文件,不會阻塞服務進程,其他的命令可以執行,但是有幾個命令是不能執行的。

save 
bgsave
bgrewriteaof

在bgsave 期間 服務器拒絕這三個命令,主要是方式線程間競爭產生問題。

通過配置文件自動生成RDB

初了手動執行這兩個命令外,還可以在配置文件中配合參數,達到條件的時候就會自動的生成RDB
打開我們的配置文件redis.conf,找到如下圖,這個是默認的配置。
在這裏插入圖片描述

save 900 1 
表示在900秒內,如果發生了一次寫操作,就觸發bgsave命令生成RDB

同理 
save 300 10 在300秒內,發生了10次寫操作,就觸發bgsave

save 60 10000  在60秒內發生了10000次寫操作,就觸發bgsave 

上面的這些可以進行配置,可以看到默認的設置,如果短時間內發生大量的寫操作就會自動的觸發bgsave ,生成RDB文件, 防止數據丟失。

好了,上面雖然說達到這三個條件中的一個,redis就會自動的生成RDB文件,那系統是怎樣控制,又是怎樣識別是否滿足條件呢?
原來啊,服務器維持了一個dirty 計數器,以及一個lastsave屬性。
dirty 計數器記錄着從上次save/bgave 到現在發生了多少次寫操作,沒進行一次寫操作,計數器就加1
比如

set a  123
計數器dirty 加1 

set a 123 b 234 c 456
計數器dirty 加3

而lastsave 是unix時間戳,記錄上次save或bgsave的時間。
有了這兩個屬性,就可以判斷什麼時候執行啦,redis服務器會週期性的執行serverCron函數,默認的話是每100毫秒執行一次。
這個serverCron 函數先通過當前時間減去lastsave 獲取時間間隔。
如果dirty 大於 saveparm.chranges
並且時間間隔大於saveparm.seconds
那麼就會觸發bgsave 生成 RDB文件

其中saveparm.seconds 和saveparm.chranges 分別對應的是配置文件中設置的save 900 1等。

既然生成了RDB文件,我們只知道RDB是一個壓縮的二進制文件,那RDB文件到底結構是什麼樣的呢?
我看了一下《redis 設計與實現》沒有怎麼看明白哈哈,感興趣的可以去看看。

RDB方式就講到這裏了,記住RDB方式,是定時的執行bgsave 命令生成RDB文件保存在磁盤上實現持久化的。適合數據備份,用於數據恢復可能會丟失最近幾分鐘的數據。

AOF

全稱是append only file. AOF 持久化的方式是通過redis服務器記錄保存下所有的寫命令到AOF文件存放在磁盤上,實現持久化的,看下圖:
在這裏插入圖片描述
怎樣採用AOF的方式持久化呢?
打開我們的配置文件,在配置文件中找到appendonly 改成yes 就可以採用AOF的方式備份了
在這裏插入圖片描述
我們啓動redis服務,爲了測試方便,我們新啓的一個redis服務,數據庫中沒有任何key
在這裏插入圖片描述
我們看看appendonly.aof 也是沒有任何東西的。
在這裏插入圖片描述
現在我們存入一個key
在這裏插入圖片描述
然後我們來看下aof文件的內容:
在這裏插入圖片描述
可以看到,初了一些$3等一些特殊符號外我們可以看到我們執行的命令。

select 0
set a bbb

但是我們一些讀操作的就不會記錄。由此可見,AOF 持久化就是將所有的寫操作存入AOF文件中,當數據恢復的時候,執行AOF文件中的命令就可以獲取數據了。

我們接着來看那,我向數據庫中先加一個key b ,然後刪除key a .
在這裏插入圖片描述
好了,現在我們再來看看aof 文件中是什麼情況。
在這裏插入圖片描述
可以看到命令有:

select 0
set a bbb
set b ddd
del a

所以aof 文件中包含了這四條命令,到這大家有沒有發現一個問題,如果我重複的對某一個key值進行操作,那麼aof文件中就會記錄所有的操作命令,但是實際上只有最後一次操作纔是有效的,那這個aof文件中是不是就有很多冗餘的數據呢?

實際上是這樣的,那怎麼解決這個問題呢?這裏就要提到一個命令啦

BGREWRITEAOF

和RDB中的save 以及bgsave 是類似的。不過bgrewriteaof 命令的作用是重寫aof文件,爲什麼要重寫呢,就是爲了解決aof文件中冗餘的問題。
我們先來手動執行一下這個命令
在這裏插入圖片描述
然後看看aof 文件中的內容
在這裏插入圖片描述
可以看到命令變成了

select 0
set b ddd

重寫之後,aof的文件裏的命令就是有效的啦,但是我們總不能自己手動執行bgrewriteaof 命令吧,那我們在哪裏配置呢?
在redis.conf 配置文件中有這兩個參數。
在這裏插入圖片描述
auto-aof-rewrite-percentage 100
當Aof log增長超過指定比例時,重寫log file, 設置爲0表示不自動重寫Aof 日誌,重寫是爲了使aof體積保持最小,而確保保存最完整的數據。

auto-aof-rewrite-min-size 64mb

觸發aof rewrite的最小文件尺寸

也就是說在實際應用中,如果開啓了aof 備份,可以設置這兩個參數來重寫AOF文件。

好了上面說了那麼多,那redis服務怎麼通過aof文件來恢復數據的呢?
其實很簡單,就是將aof 文件中的命令一條一條的讀取出來執行。看下圖
在這裏插入圖片描述

最後再說一點嘿嘿。
我們在配置文件中同時啓用了RDB 和AOF ,那麼服務啓動的時候,會在用那個文件來回複數據呢?
看下面這張圖。
在這裏插入圖片描述
可以看到如果啓動aof ,就會採用aof 文件來回複數據,這是爲什麼呢,因爲AOF 文件更新的頻率更高,模式一秒中一次,所以用AOF 恢復的數據更加準確。

好了,只有這麼多了哈哈,推薦大家看看《redis 設計與實現》也不建議大家從頭往後看,調感興趣的看吧,畢竟裏面還是有很多原理對我們而言也不是一定非得弄懂的,大概瞭解一下就行,我比較懶哈哈。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章