Redis
做爲一款內存數據庫,被普遍使用於緩存,分佈式鎖等場景,那麼假如斷電或者因其餘因素致使 Reids
服務宕機,在重啓以後數據會丟失嗎?java
Redis
雖然是定義爲一個內存數據庫,可是其也支持數據的持久化,在 Redis
中提供了兩種持久化機制:RDB
持久化和 AOF
持久化。redis
RDB
全稱爲:Redis DataBase
,是 Redis
當中默認的持久化方案。當觸發持久化條件時,Redis
默認會生成一個 dump.rdb
文件,Redis
在重啓的時候就會經過解析 dump.rdb
文件進行數據恢復。數據庫
RDB
持久化機制有兩種觸發方式:自動觸發和手動觸發。promise
自動觸發方式也能夠分爲三種:緩存
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
時間戳。app
除了上面提到的觸發生成 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
的兩種持久化機制:RDB
和 AOF
,並分別介紹了兩種持久化機制的原理,經過對兩種持久化機制的對比分析了兩種持久化機制各自的優勢和缺點。