這篇文章將為大家詳細講解有關斷電后Redis數據不會丟失的原因是什么,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
Redis
作為一款內存數據庫,被廣泛使用于緩存,分布式鎖等場景,那么假如斷電或者因其他因素導致 Reids
服務宕機,在重啟之后數據會丟失嗎?
Redis
雖然是定義為一個內存數據庫,但是其也支持數據的持久化,在 Redis
中提供了兩種持久化機制:RDB
持久化和 AOF
持久化。
RDB
全稱為:Redis DataBase
,是 Redis
當中默認的持久化方案。當觸發持久化條件時,Redis
默認會生成一個 dump.rdb
文件,Redis
在重啟的時候就會通過解析 dump.rdb
文件進行數據恢復。
RDB
持久化機制有兩種觸發方式:自動觸發和手動觸發。
自動觸發方式也可以分為三種:
執行 flushall
命令(flushdb
命令不會觸發)時,不過此時生成的 dump
文件內的數據是空的(dump
文件還會存儲一些頭信息,所以文件本身是有內容的,只是沒有數據),沒有什么太大的實際意義。
執行 shutdown
命令時會觸發生成 dump
文件。
通過配置文件自動生成,Redis
中配置文件默認配置如下,只要達到這三個條件中的任意一個,就會觸發 Redis
的RDB
持久化機制。
save 900 1 //900秒內至少有1個key被添加或者更新 save 300 10 //300秒內至少有10個key被添加或者更新 save 60 10000 //60秒內至少有10000個key被添加或者更新
手動觸發
除了自動觸發,Redis
中還提供了 2
個手動觸發 RDB
機制的命令(這兩個命令不能同時被執行,一旦一個命令正在執行中,另一個命令會被拒絕執行):
save
:這個命令會阻塞 Redis
服務器進程,直到成功創建 RDB
文件,也就是說在生成 RDB
文件之前,服務器不能處理客戶端發送的任何命令。
bgsave
:父進程會執行 fork
操作來創建一個子進程。RDB
文件由子進程來負責生成,父進程可以正常處理客戶端發送的命令(這里也是 Redis
不僅僅只是單線程的一個體現)。
如果想要知道上一次成功執行 save
或者 bgsave
命令的時間,可以執行 lastsave
命令進行查看,lastsave
命令返回的是一個 unix
時間戳。
除了上面提到的觸發生成 rdb
文件的配置參數,RDB
持久化機制還有如下一些相關命令:
dir
:rdb
文件生成目錄。默認是 ./
(當前目錄),可以執行命令 config get dir
進行查看,如下圖所示說明當前 dump
文件生成目錄為 /usr/local/redis-5.0.5/bin
:
dbfilename
:rdb
文件名。默認是 dump.rdb
。
rdbcompression
:rdb
文件是否是 LZF
壓縮文件。默認是 yes
。
rdbchecksum
:是否開啟數據校驗。默認是 yes
。
RDB
是一個非常緊湊的壓縮文件,保存了不同時間點上的文件,非常適合用來災備和數據恢復。
RDB
最大限度地提高了 Redis
的性能,因為 Redis
父進程需要做的唯一的工作就是派生一個子進程來完成剩下的工作,父進程永遠不會執行磁盤 I/O
或類似的耗時操作。
與后面介紹的 AOF
持久化機制比較,RDB
方式恢復數據的速度更快。
RDB
無法做到實時備份,所以如果 Redis
因異常停止工作而沒有正確的關機,那么從上一次備份的到異常宕機的這一段時間的數據將會丟失。
RDB
通常需要父進程來執行 fork
操作創建子線程,所以如果頻繁執行 fork
操作而 CPU
性能又不是很高的話可能會造成短時間內父進程不可用。
AOF
全稱為:Append Only File
,是 Redis
當中提供的另一種持久化機制。AOF
采用日志的形式將每個寫操作追加到文件中。開啟 AOF
機制后,只要執行更改 Redis
數據的命令時,命令就會被寫入到 AOF
文件中。在 Redis
重啟的時候會根據日志內容依次執行 AOF
文件中的命令來恢復數據。
AOF
和 RDB
最大的不同是:AOF
記錄的是執行命令(類似于 MySQL
中 binlog
的 statement
格式),而RDB
記錄的是數據(類似于 MySQL
中 binlog
的 row
格式)。
需要注意的是:假如同時開啟了 RDB
和 AOF
兩種機制,那么 Redis
會優先選擇 AOF
持久化文件來進行數據恢復。
AOF
機制默認是關閉的,可以通過以下配置文件進行修改
appendonly no //是否開啟AOF機制,默認是no表示關閉,修改為yes則表示開啟 appendfilename "appendonly.aof" //AOF文件名
PS:和 RDB
機制一樣,其生成文件的路徑也是通過 dir
屬性進行配置。
AOF
機制下數據是否實時寫入磁盤,這個和 MySQL
的 redo log
機制很類似,也是需要通過參數來進行控制。
AOF
數據何時寫入磁盤由參數 appendfsync
來進行控制:
appendfsync | 描述 | 備注 |
---|---|---|
always | 寫入緩存的同時通知操作系統刷新(fsync)到磁盤(但是也可能會有部分操作系統只是盡快刷盤,而不是實時刷盤) | Slow, Safest |
everysec | 先寫入緩存,然后每秒中刷一次盤(默認值),這種模式極端情況可能會丟失 1s 的數據 | Compromise |
no | 只寫入緩存,什么時候刷盤由操作系統自己決定 | Faster |
AOF
機制主要是通過記錄執行命令的方式來實現的,那么隨著時間的增加,AOF
文件不可避免的會越來越大,而且可能會出現很多冗余命令。比如同一個 key
值執行了 10000
次 set
操作,實際上前面 9999
次對恢復數據來說都是沒用的,只需要執行最后一次命令就可以把數據恢復,正是為了避免這種問題,AOF
機制就提供了文件重寫功能。
重寫原理分析
AOF
重寫時 Redis
并不會去分析原有的文件,因為如果原有文件過大,分析也會很耗時,所以 Redis
選擇的做法就是重新去 Redis
中讀取現有的鍵值對,然后用一條命令記錄鍵值對的值。
只使用一條命令也有一個前提,那就是一個集合鍵或者列表鍵或者哈希鍵內包含的元素不能超過 64
個,一旦超過 64
個,就會使用多條命令來進行記錄。
AOF
重寫的時候一般都會有大量的寫操作,所以為了不阻塞客戶端的命令請求,Redis
會把重寫操作放入到子進程中執行,但是放入子進程中執行也會帶來一個問題,那就是重寫期間如果同時又執行了客戶端發過來的命令,又該如何保證數據的一致性?
為了解決數據不一致問題,Redis
中引入了一個 AOF
重寫緩沖區。當開始執行 AOF
文件重寫之后又接收到客戶端的請求命令,不但要將命令寫入原本的 AOF
緩沖區(根據上面提到的參數刷盤),還要同時寫 入 AOF
重寫緩沖區:
一旦子進程完成了 AOF
文件的重寫,此時會向父進程發出信號,父進程收到信號之后會進行阻塞(阻塞期間不執行任何命令),并進行以下兩項工作:
將 AOF
重寫緩沖區的文件刷新到新的 AOF
文件內。
將新 AOF
文件進行改名并原子的替換掉舊的 AOF
文件。
完成了上面的兩項工作之后,整個 AOF
重寫工作完成,父進程開始正常接收命令。
AOF
機制的觸發條件同樣也分為自動觸發和手動觸發。
自動觸發:自動觸發可以通過以下參數進行設置:
auto-aof-rewrite-percentag //文件大小超過上次AOF重寫之后的文件的百分比。默認100,也就是默認達到上一次AOF重寫文件的2倍之后會再次觸發AOF重寫 auto-aof-rewrite-min-size //設置允許重寫的最小AOF文件大小,默認是64M。主要是避免滿足了上面的百分比,但是文件還是很小的情況。
手動觸發:執行 bgrewriteaof
命令。
注意:bgrewriteaof
命令也不能和上面 RDB
持久化命令 bgsave
同時執行,這么做是為了避免同時創建兩個子進程來同時執行大量寫磁盤操作,影響到 Redis
的性能。
使用 AOF
機制,可以自由選擇不同 fsync
(刷盤)策略,而且在默認策略下最多也僅僅是損失 1s
的數據。
AOF
日志是一個僅追加的日志,因此如果出現斷電,也不存在查找或損壞問題。即使由于某些原因(磁盤已滿或其他原因),日志已經寫了一半的命令結束,redis-check-aof工具也能夠輕松地修復它。
當 AOF
文件變得太大時,Redis
能夠在后臺自動重寫。
不同于 RDB
的文件格式,AOF
是一種易于理解和解析的格式,依次包含所有操作的日志。
對于相同的數據集,AOF
文件通常比等效的 RDB
文件大。
根據 fsync
的具體策略,AOF
機制可能比 RDB
機制慢。但是一般情況下,fsync
設置為每秒的性能仍然很高,禁用 fsync
后,即使在高負載下,它的速度也能和 RDB
一樣快。
因為 AOF
文件是追加形式,可能會遇到 BRPOP
、LPUSH
等阻塞命令的錯誤,從而導致生成的 AOF
在重新加載時不能復制完全相同的數據集,而 RDB
文件每次都是重新從頭創建快照,這在一定程度上來說 RDB
文件更加健壯。
關于“斷電后Redis數據不會丟失的原因是什么”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。