為什么要持久化
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以上。
聲明: 公眾號如需轉載該篇文章,發表文章的頭部一定要 告知是轉至公眾號: 后端元宇宙。同時也可以問本人要markdown原稿和原圖片。其它情況一律禁止轉載!

