什么是Redis持久化?
Redis是鍵值對的內存數據庫,它將數據存儲在內存里。客戶端發送命令到服務器,再由服務器到內存里查找數據。
一旦Redis服務器進程退出,存儲在內存里的數據就會丟失。
為了解決這個問題,Redis提供了持久化機制,即將數據保存到磁盤里,以便Redis服務器進程初始化或重啟后重新加載數據,避免數據丟失。
Redis提供兩種持久化方案,分別是RDB(Redis DataBase)和AOF(Append Only File)。
RDB持久化
RDB采用快照的方式來實現持久化,把數據庫數據保存到RDB文件里,也可以通過RDB文件還原數據庫數據。
開啟RDB持久化的方式
RBD是Redis默認的持久化方案,可以通過三種方式來生成RDB文件:SAVE、BGSAVE和自動觸發,其中前兩種是主動操作,后一種是被動操作,由Redis服務器控制。
SAVE
SAVE命令會阻塞Redis服務器進程,直到RDB文件創建完成,在服務器進程阻塞期間,服務器不能處理任何命令請求。
redis> Save // 等待直到RDB文件創建完成
OK
BGSAVE
和SAVE命令直接阻塞服務器進程不同,BGSAVE命令會fork一個子進程來負責創建RDB文件,服務器進程繼續處理命令請求。
redis> BGSAVE // fork子進程,並由子進程創建RDB文件
Background saving started
自動觸發
Redis允許用戶通過設置服務器配置的save選項,讓服務器每隔一段時間自動執行一次BGSAVE命令。用戶可以通過save選項設置多個條件,只要滿足其中任意一個條件,服務器就會執行BGSAVE命令。
save 900 1 // 服務器在900秒內,至少1次修改
save 300 10 // 服務器在300秒內,至少10次修改
save 60 10000 // 服務器在60秒內,至少10000次修改
AOF持久化
除了RDB外,Redis還提供了AOF。與RDB通過保存數據庫快照不同,AOF是通過保存命令來記錄數據庫數據的。默認情況下,Redis是沒有開啟AOF的,可以通過配置redis.conf文件來開啟AOF持久化,關於AOF的配置如下:
# appendonly參數開啟AOF持久化
appendonly no
# AOF持久化的文件名,默認是appendonly.aof
appendfilename "appendonly.aof"
# AOF文件的保存位置和RDB文件的位置相同,都是通過dir參數設置的
dir ./
# 同步策略
# appendfsync always
appendfsync everysec
# appendfsync no
# aof重寫期間是否同步
no-appendfsync-on-rewrite no
# 重寫觸發配置
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# 加載aof出錯如何處理
aof-load-truncated yes
# 文件重寫策略
aof-rewrite-incremental-fsync yes
AOF持久化實現
AOF需要記錄Redis的每個命令,步驟分為:命令追加(append)、文件寫入(write)和文件同步(sync)。
命令追加
當AOF持久化功能處於打開狀態時,服務器在執行完一個寫命令之后,會以協議格式將被執行的寫命令追加到服務器狀態的 aof_buf
緩沖區的末尾。
文件寫入和同步
關於何時將 aof_buf
緩沖區的內容寫入AOF文件中,Redis提供了三種策略:
appendfsync always
:將aof_buf
緩沖區中的所有內容寫入並同步到AOF文件。appendfsync everysec
:將aof_buf
緩沖區中的所有內容寫入到AOF文件,如果上次同步AOF文件的時間距離現在超過1秒,那么兩次對AOF文件進行同步,並且這個同步操作是由一個線程專門負責執行的。appendfsync no
:將aof_buf
緩沖區中的所有內容寫入到AOF文件,但並不對AOF文件進行同步,何時同步由操作系統來決定。
關於AOF的同步策略是涉及到操作系統的 write
函數和 fsync
函數的,在《Redis設計與實現》中是這樣說明的:
為了提高文件寫入效率,在現代操作系統中,當用戶調用
write
函數,將一些數據寫入文件時,操作系統通常會將數據暫存到一個內存緩沖區里,當緩沖區的空間被填滿或超過了指定時限后,才真正將緩沖區的數據寫入到磁盤里。
這樣的操作雖然提高了效率,但也為數據寫入帶來了安全問題:如果計算機停機,內存緩沖區中的數據會丟失。為此,系統提供了fsync
、fdatasync
同步函數,可以強制操作系統立刻將緩沖區中的數據寫入到硬盤里,從而確保寫入數據的安全性。
AOF重寫
AOF會記錄每個Redis命令到AOF文件,隨着時間越來越長,AOF文件會變得越來越大。如果不加以控制,會對Redis服務器,甚至對操作系統造成影響,而且AOF文件越大,數據恢復也越慢。
為了解決AOF文件體積膨脹的問題,Redis提供AOF文件重寫功能來對AOF文件進行“瘦身”。Redis通過創建一個新的AOF文件來替換現有的AOF,新舊兩個AOF文件保存的數據相同,但新AOF文件沒有了冗余命令。
RDB和AOF對比
關於RDB和AOF的優缺點,官網上面也給了比較詳細的說明redis.io/topics/pers…
RDB
優點:
- RDB快照是一個壓縮過的非常緊湊的文件,保存着某個時間點的數據集,適合做數據的備份,災難恢復;
- 可以最大化Redis的的性能,在保存RDb文件,服務器進程只需要fork一個子進程來完成RDB文件的創建,父進程不需要做IO操作;
- 與AOF相比,恢復大數據集的時候會更快;
缺點:
- RDB的數據安全性是不如AOF的,保存整個數據集的過程是比繁重的,根據配置可能要幾分鍾才快照一次,如果服務器宕機,那么就可能丟失幾分鍾的數據;
- Redis數據集較大時,fork的子進程要完成快照會比較耗CPU、耗時;
AOF
優點:
- 數據更完整,安全性更高,秒級數據丟失(取決fsync策略,如果是everysec,最多丟失1秒的數據);
- AOF文件是一個只進行追加的日志文件,且寫入操作是以Redis協議的格式保存的,內容是可讀的,適合誤刪緊急恢復;
缺點:
- 對於相同的數據集,AOF文件的體積要大於RDB文件,數據恢復也會比較慢;
- 根據所使用的fsync策略,AOF的速度可能會慢於RDB。 不過在一般情況下,每秒fsync的性能依然非常高;
RDB和AOF如何選擇
通常來說,應該同時使用兩種持久化方案,以保證數據安全。
- 如果數據不敏感,且可以從其他地方重新生成,可以關閉持久化。
- 如果數據比較重要,且能夠承受幾分鍾的數據丟失,比如緩存等,只需要使用RDB即可。
- 如果是用做內存數據,要使用Redis的持久化,建議是RDB和AOF都開啟。
當RDB與AOF兩種方式都開啟時,Redis會優先使用AOF恢復數據,因為AOF保存的文件比RDB文件更完整。