一文讓你明白Redis持久化(RDB、AOF)

為什麼要持久化

Redis是記憶體資料庫,如果不將記憶體中的資料庫狀態保存到磁碟中,那麼一旦伺服器進程退出,伺服器的資料庫狀態就會消失(即斷電即失)。為了保證數據不丟失,我們需要將
記憶體中的數據存儲到磁碟,以便 Redis 重啟時能夠從磁碟中恢復原有的數據,而整個過程就叫做 Redis 持久化。

Redis 持久化也是 Redis 和 Memcached 的主要區別之一,因為 Memcached 是不具備持久化功能的。

持久化的幾種方式

Redis 持久化擁有以下三種方式:

快照方式(RDB, Redis DataBase)將某一個時刻的記憶體數據,以二進位的方式寫入磁碟;

文件追加方式(AOF, Append Only File),記錄所有的寫操作命令,並以文本的形式追加到文件中;

混合持久化方式,Redis 4.0 之後新增的方式,混合持久化是結合了 RDB 和 AOF 的優點,在寫入的時候,先把當前的數據以 RDB 的形式寫入文件的開頭,再將後續的操作命令

以 AOF 的格式存入文件,這樣既能保證 Redis 重啟時的速度,又能避免數據丟失的風險。

因為每種持久化方案,都有特定的使用場景,讓我們先從 RDB 持久化說起吧。

一、什麼是RDB,RDB如何實現持久化?

1、什麼是RDB?

RDB是Redis Database 的縮寫,其作用是在某一個時間點,將Redis存儲在記憶體中的數據生成快照並存儲到磁碟等介質上,存在這個磁碟介質上的文件就是RDB文件。「快照」顧名

思義就是好像照相一樣保存當時的數據,這裡RDB文件是一個二進位的文件,並且是經過壓縮的。因為RDB文件是保存在硬碟中的,即使Redis伺服器進程退出,甚至運行Redis

伺服器的電腦宕機,但只要RDB文件仍然存在,Redis伺服器就可以用它來還原資料庫狀態。

2、觸發方式(手動、自動)

RDB 的持久化觸發方式有兩類:一類是手動觸發,另一類是自動觸發。

1)手動觸發(執行 save 或者 bgsave 命令)

手動觸發持久化的操作有兩個命令: save 和 bgsave ,它們主要區別體現在:是否阻塞 Redis 主執行緒的執行

save命令

redis 127.0.0.1:6379> SAVE

在客戶端中執行 save 命令,就會觸發 Redis 的持久化,但同時也是使 Redis 處於阻塞狀態,直到 RDB 持久化完成,才會響應其他客戶端發來的命令,

所以在生產環境一定要慎用

bgsave命令

redis 127.0.0.1:6379> BGSAVE

bgsave(background save)既後台保存的意思, 它和 save 命令最大的區別就是 bgsave 會 fork() 一個子進程來執行持久化,整個過程中只有在 fork() 子進程時有短暫的

阻塞,當子進程被創建之後,Redis 的主進程就可以響應其他客戶端的請求了,相對於整個流程都阻塞的 save 命令來說,顯然 bgsave 命令更適合我們使用。

在快照進行的過程中,也就是生成文件的過程中,不會對原有的RDB文件進行修改,直到快照生成完畢,直接將老的替換成新的,保證rdb文件任何時刻都是完整的。

2) 自動觸發

自動觸發的含義就是不用我們手動命令去觸發持久化,而是通過配置當滿足某一規則的時候自動去執行 bgsave 命令。

Redis的配置文件就默認設置了3個保存點:

# 以下配置表示的條件:
# 900秒內有1個key發生了變化,則觸發保存RDB文件
save 900 1
# 伺服器在300秒之內被修改了10次
save 300 10
# 伺服器在60秒之內被修改了10000次
save 60 10000

#如果想禁用快照保存的功能,可以通過注釋掉所有"save"配置達到,或者在最後一條"save"配置後添加如下的配置:
save ""

注意這裡滿足條件執行的是bgsave命令。

二、什麼是AOF,AOF如何實現持久化?

1、什麼是AOF?

以日誌的形式來記錄每個寫操作,將Redis執行過的所有寫指令記錄下來(讀操作不記錄),只許追加文件但不可以改寫文件,redis啟動之初會讀取該文件重新構建數據,

換言之,redis重啟的話就根據日誌文件的內容將寫指令從前到後執行一次以完成數據的恢復工作 。

默認情況下,redis是沒有開啟AOF(append only file)的。開啟AOF功能需要設置配置:appendonly yes 。

2、AOF持久化流程

上面提到了AOF持久化的過程就是日誌不斷追加的過程,這裡通過圖 給大家介紹具體流程:

1、Client作為命令的來源,會有多個源頭以及源源不斷的請求命令。

2、在這些命令到達Redis Server 以後,並不是直接寫入AOF文件,會將其這些命令先放入AOF快取中進行保存。這裡的AOF緩衝區實際上是記憶體中的一片區域,存在的目

的是當這些命令達到一定量以後再寫入磁碟,避免頻繁的磁碟IO操作。

3、AOF緩衝會根據對應的策略將命令寫入磁碟上的AOF文件。

4、AOF文件隨著寫入文件內容的增加,會根據規則進行命令的合併,這裡叫做AOF重寫,從而起到AOF文件壓縮的目的。

5、當Redis Server 伺服器重啟的時候會從AOF文件載入數據。

這裡面有兩點需要在詳細寫: AOF緩衝區同步文件策略AOF重寫機制

3、AOF緩衝區同步文件策略

上面提到了Redis 會將命令先寫入到AOF緩衝區,再寫入AOF文件。這裡介紹一下AOF緩衝區同步文件的三個策略。

#aof持久化策略的配置
appendfsync always    #always表示每次寫入都執行fsync,以保證數據同步到磁碟
appendfsync everysec   #everysec表示每秒執行一次fsync,可能會導致丟失這1s數據
appendfsync no   #no表示不執行fsync,由作業系統保證數據同步到磁碟,速度最快

Always策略 的同步操作是在主進程的主執行緒中進行的,由於fsync的阻塞特性,會導致其掛起,在此期間無法服務新的請求,因而吞吐量下降,但確實能夠保證記憶體和硬碟中

數據的一致性。

Everysec策略 的同步操作是通過後台I/O執行緒進行的,由於是在子執行緒中進行,所以主執行緒並不會被阻塞,可以繼續服務新的請求,但是記憶體和硬碟中的數據會有1秒的差別

(不一定精準),這是一種折衷的方案,尋求了一個平衡。

No策略 則是將同步操作的控制權交由作業系統,不阻塞主執行緒,但是數據一致性可能會偏差很大

官方建議使用默認配置每秒同步,它既快速又安全。這個always策略在實踐中非常緩慢, 沒有辦法做得fsync比現在更快。

4、AOF重寫機制

(1)是什麼?

AOF採用文件追加方式,文件會越來越大為避免出現此種情況,新增了重寫機制,當AOF文件的大小超過所設定的閾值時,Redis就會啟動AOF文件的內容壓縮, 只保留可以恢復

數據的最小指令集。

舉個例子:比如有個key 一開始你 set key 1,然後改成 set key 2,最後 set key 3。如果不重寫那麼這3條語句都在文件中,這樣即占空間,啟動的時候都要執行一遍無效

的命令,如果重寫後,只需要保存set key 3 就可以了。

AOF重寫不僅降低了文件的佔用空間,同時更小的AOF也可以更快地被Redis載入。

(2)觸發機制(手動、自動)

手動:客戶端向伺服器發送bgrewriteaof命令

自動:滿足配置文件中的選項後,自動執行bgrewriteaof命令。Redis會記錄上次重寫時的AOF大小,默認配置是當AOF文件大小是上次rewrite後大小的一倍且文件大於64M時

觸發。

(3)重寫原理

AOF文件持續增長而過大時,會fork出一條新進程來將文件重寫(也是先寫臨時文件最後再rename),遍歷新進程的記憶體中數據,每條記錄有一條的Set語句。重寫aof文件的操作,

並沒有讀取舊的aof文件, 而是將整個記憶體中的資料庫內容用命令的方式重寫了一個新的aof文件,這點和快照有點類似。

三、RDB和AOF各自優缺點

1、RDB的優點

(1)比起AOF,在數據量比較大的情況下,RDB的啟動速度更快。

(2)RDB文件是一個很簡潔的單文件,它保存了某個時間點的Redis數據,很適合用於做備份。

(3)RDB的性能很好,需要進行持久化時,主進程會fork一個子進程出來,然後把持久化的工作交給子進程,自己不會有相關的I/O操作。

2、RDB缺點

(1)RDB容易造成數據的丟失。假設每5分鐘保存一次快照,如果Redis因為某些原因不能正常工作,那麼從上次產生快照到Redis出現問題這段時間的數據就會丟失了。

(2)RDB使用fork()產生子進程的過程會堵塞主進程,所以數據比較大的話 fork() 可能很耗時,就會造成Redis停止服務幾毫秒。

3、AOF優點

(1)該機制可以帶來更高的數據安全性,即數據持久性。Redis中提供了3中同步策略,即每秒同步、每修改同步和不同步。事實上,每秒同步也是非同步完成的,其效率也是非常

高的,如果發生災難,您只可能會丟失1秒的數據。

(2)AOF日誌文件是一個純追加的文件。就算伺服器突然Crash,也不會出現日誌的定位或者損壞問題。甚至如果因為某些原因(例如磁碟滿了)命令只寫了一半到日誌文件里,

我們也可以用redis-check-aof這個工具很簡單的進行修復。

(3)當AOF文件太大時,Redis會自動在後台進行重寫。重寫很安全,因為重寫是在一個新的文件上進行。

4、AOF缺點

(1)在相同的數據集下,AOF文件的大小一般會比RDB文件大。

(2)AOF開啟後,寫QPS會比RDB的低。通常fsync設置為每秒一次就能獲得比較高的性能,而在禁止fsync的情況下速度可以達到RDB的水平。

四、生產配置持久化的一些意見

(1)官方建議:是同時開啟兩種持久化策略。因為有時需要RDB快照是進行資料庫備份,更快重啟以及發生AOF引擎錯誤的解決辦法。(換句話就是通過RDB來多備份一份數據

總是好的)

(2) 因為RDB文件只用作後備用途,建議只在Slave上持久化RDB文件,而且只要15分鐘備份一次就夠了,只保留save 900 1這條規則。

(3)如果選擇AOF,只要硬碟許可,應該盡量減少AOF rewrite的頻率。因為一是帶來了持續的IO,二是AOF rewrite的最後將rewrite過程中產生的新數據寫到新文件造成的阻塞

幾乎是不可避免的。AOF重寫的基礎大小默認值64M太小了,可以設到2G以上。