Redis雖然是一種內(nèi)存型數(shù)據(jù)庫,一旦服務(wù)器進程退出,數(shù)據(jù)庫的數(shù)據(jù)就會丟失,為了解決這個問題Redis提供了兩種持久化的方案,將內(nèi)存中的數(shù)據(jù)保存到磁盤中,避免數(shù)據(jù)的丟失。
RDB持久化
redis提供了RDB持久化的功能,這個功能可以將redis在內(nèi)存中的的狀態(tài)保存到硬盤中,它可以手動執(zhí)行,也可以再redis.conf中配置,定期執(zhí)行。
RDB持久化產(chǎn)生的RDB文件是一個經(jīng)過壓縮的二進制文件,這個文件被保存在硬盤中,redis可以通過這個文件還原數(shù)據(jù)庫當(dāng)時的狀態(tài)。
RDB的創(chuàng)建與載入
RDB文件可以通過兩個命令來生成:
-
SAVE:阻塞redis的服務(wù)器進程,直到RDB文件被創(chuàng)建完畢。 -
BGSAVE:派生(fork)一個子進程來創(chuàng)建新的RDB文件,記錄接收到BGSAVE當(dāng)時的數(shù)據(jù)庫狀態(tài),父進程繼續(xù)處理接收到的命令,子進程完成文件的創(chuàng)建之后,會發(fā)送信號給父進程,而與此同時,父進程處理命令的同時,通過輪詢來接收子進程的信號。
而RDB文件的載入一般情況是自動的,redis服務(wù)器啟動的時候,redis服務(wù)器再啟動的時候如果檢測到RDB文件的存在,那么redis會自動載入這個文件。
如果服務(wù)器開啟了AOF持久化,那么服務(wù)器會優(yōu)先使用AOF文件來還原數(shù)據(jù)庫狀態(tài)。
RDB是通過保存鍵值對來記錄數(shù)據(jù)庫狀態(tài)的,采用copy on write的模式,每次都是全量的備份。
自動保存間隔
BGSAVE可以在不阻塞主進程的情況下完成數(shù)據(jù)的備份??梢酝ㄟ^redis.conf中設(shè)置多個自動保存條件,只要有一個條件被滿足,服務(wù)器就會執(zhí)行BGSAVE命令。
# 以下配置表示的條件:
# 服務(wù)器在900秒之內(nèi)被修改了1次
save 900 1
# 服務(wù)器在300秒之內(nèi)被修改了10次
save 300 10
# 服務(wù)器在60秒之內(nèi)被修改了10000次
save 60 10000
AOF持久化
AOF持久化(Append-Only-File),與RDB持久化不同,AOF持久化是通過保存Redis服務(wù)器鎖執(zhí)行的寫狀態(tài)來記錄數(shù)據(jù)庫的。
具體來說,RDB持久化相當(dāng)于備份數(shù)據(jù)庫狀態(tài),而AOF持久化是備份數(shù)據(jù)庫接收到的命令,所有被寫入AOF的命令都是以redis的協(xié)議格式來保存的。
在AOF持久化的文件中,數(shù)據(jù)庫會記錄下所有變更數(shù)據(jù)庫狀態(tài)的命令,除了指定數(shù)據(jù)庫的select命令,其他的命令都是來自client的,這些命令會以追加(append)的形式保存到文件中。
服務(wù)器配置中有一項appendfsync,這個配置會影響服務(wù)器多久完成一次命令的記錄:
-
always:將緩存區(qū)的內(nèi)容總是即時寫到AOF文件中。 -
everysec:將緩存區(qū)的內(nèi)容每隔一秒寫入AOF文件中。 -
no:寫入AOF文件中的操作由操作系統(tǒng)決定,一般而言為了提高效率,操作系統(tǒng)會等待緩存區(qū)被填滿,才會開始同步數(shù)據(jù)到磁盤。
redis默認實用的是everysec。
redis在載入AOF文件的時候,會創(chuàng)建一個虛擬的client,把AOF中每一條命令都執(zhí)行一遍,最終還原回數(shù)據(jù)庫的狀態(tài),它的載入也是自動的。在RDB和AOF備份文件都有的情況下,redis會優(yōu)先載入AOF備份文件
AOF文件可能會隨著服務(wù)器運行的時間越來越大,可以利用AOF重寫的功能,來控制AOF文件的大小。AOF重寫功能會首先讀取數(shù)據(jù)庫中現(xiàn)有的鍵值對狀態(tài),然后根據(jù)類型使用一條命令來替代前的鍵值對多條命令。
AOF重寫功能有大量寫入操作,所以redis才用子進程來處理AOF重寫。這里帶來一個新的問題,由于處理重新的是子進程,這樣意味著如果主線程的數(shù)據(jù)在此時被修改,備份的數(shù)據(jù)和主庫的數(shù)據(jù)將會有不一致的情況發(fā)生。因此redis還設(shè)置了一個AOF重寫緩沖區(qū),這個緩沖區(qū)在子進程被創(chuàng)建開始之后開始使用,這個期間,所有的命令會被存兩份,一份在AOF緩存空間,一份在AOF重寫緩沖區(qū),當(dāng)AOF重寫完成之后,子進程發(fā)送信號給主進程,通知主進程將AOF重寫緩沖區(qū)的內(nèi)容添加到AOF文件中。
相關(guān)配置
#AOF 和 RDB 持久化方式可以同時啟動并且無沖突。
#如果AOF開啟,啟動redis時會加載aof文件,這些文件能夠提供更好的保證。
appendonly yes
# 只增文件的文件名稱。(默認是appendonly.aof)
# appendfilename appendonly.aof
#redis支持三種不同的寫入方式:
#
# no:不調(diào)用,之等待操作系統(tǒng)來清空緩沖區(qū)當(dāng)操作系統(tǒng)要輸出數(shù)據(jù)時。很快。
# always: 每次更新數(shù)據(jù)都寫入僅增日志文件。慢,但是最安全。
# everysec: 每秒調(diào)用一次。折中。
appendfsync everysec
# 設(shè)置為yes表示rewrite期間對新寫操作不fsync,暫時存在內(nèi)存中,等rewrite完成后再寫入.官方文檔建議如果你有特殊的情況可以配置為'yes'。但是配置為'no'是最為安全的選擇。
no-appendfsync-on-rewrite no
# 自動重寫只增文件。
# redis可以自動盲從的調(diào)用‘BGREWRITEAOF’來重寫日志文件,如果日志文件增長了指定的百分比。
# 當(dāng)前AOF文件大小是上次日志重寫得到AOF文件大小的二倍時,自動啟動新的日志重寫過程。
auto-aof-rewrite-percentage 100
# 當(dāng)前AOF文件啟動新的日志重寫過程的最小值,避免剛剛啟動Reids時由于文件尺寸較小導(dǎo)致頻繁的重寫。
auto-aof-rewrite-min-size 64mb
對比
-
AOF更安全,可將數(shù)據(jù)及時同步到文件中,但需要較多的磁盤IO,AOF文件尺寸較大,文件內(nèi)容恢復(fù)相對較慢, 也更完整。 -
RDB持久化,安全性較差,它是正常時期數(shù)據(jù)備份及master-slave數(shù)據(jù)同步的最佳手段,文件尺寸較小,恢復(fù)數(shù)度較快。