Redis
是一個基於內存的非關係型的數據庫,數據保存在內存中,可是內存中的數據也容易發生丟失。這裏Redis就爲咱們提供了持久化的機制,分別是
RDB(Redis DataBase)
和
AOF(Append Only File)
。
Redis在之前的版本中是單線程的,而在6.0後對Redis的io模型作了優化,io Thread
爲多線程的,可是worker Thread
仍然是單線程。redis
在Redis啓動的時候就會去加載持久化的文件,若是沒有就直接啓動,在啓動後的某一時刻由繼續持久化內存中產生的數據。數據庫
接下來咱們就來詳細瞭解Redis的兩種持久化機制RDB(Redis DataBase)
和AOF(Append Only File)
。緩存
什麼是RDB持久化呢?RDB持久化就是將當前進程的數據以生成快照的形式持久化到磁盤中。對於快照的理解,咱們能夠理解爲將當前線程的數據以拍照的形式保存下來。安全
RDB持久化的時候會單獨fork一個與當前進程一摸同樣的子進程來進行持久化,所以RDB持久化有以下特色:bash
開機恢復數據快。服務器
寫入持久化文件快。多線程
RDB的持久化也是Redis默認的持久化機制,它會把內存中的數據以快照的形式寫入默認文件名爲dump.rdb
中保存。app
在安裝後的Redis中,Redis的配置都在redis.conf
文件中,以下圖所示,dbfilename
就是配置RDB的持久化文件名。
異步
在RDB機制中觸發內存中的數據進行持久化,有如下三種方式:ide
(1)save命令:
save命令不會fork子進程,經過阻塞當前Redis服務器,直到RDB完成爲止,因此該命令在生產中通常不會使用。save命令執行原理圖以下:
dir
的配置就是RDB持久化後生成rdb二進制文件所在的位置,默認的位置是
./
,表示當前位置,哪裏啓動redis,就會在哪裏生成持久化文件,以下圖所示:
/root/redis-4.0.6/src/redis-server /root/redis-4.0.6/redis.conf
接着經過該命令:ps -aux | grep redis
,查看咱們的redis服務是否正常啓動,如果顯示以下圖所示,則表示Redis是正常啓動的:
save
命令,在該文件夾下就會出現
dump.rdb
持久化的數據文件。
./
文件,通常咱們會把它改爲服務器本身的特定位置下,原理都是同樣的,能夠本身進行嘗試,這裏再也不進行演示。
(2)bgsave命令:
bgsave
命令會在後臺fork一個與Redis主線程一摸同樣的子線程,由子線程負責內存中的數據持久化。
這樣fork與主線程同樣的子線程消耗了內存,可是不會阻塞主線程處理客戶端請求,是以空間換時間的方式快照內存中的數據到到文件中。
bgsave
命令阻塞只會發生在fork子線程的時候,這段時間發生的很是短,能夠忽略不計,以下圖是 bgsave執行的流程圖:
dir
配置是配置持久化文件生成的指定的目錄,
dbfilename
是配置生成的文件名,也能夠經過命令行使用命令來動態的設置這兩個配置,命令以下:
config set dir{newDir}
config set dbfilename{newFileName}
(3)自動化
除了上面在命令行使用save和bgsave命令觸發持久化,也能夠在redis.conf
配置文件中,完成配置,以下圖所示:
save 900 1
表示900秒內若是至少有1個key值變化,則進行持久化保存數據;
save 300 10
則表示300秒內若是至少有10個key值發生變化,則進行持久化,save 60 10000
以此類推。
經過以上的分析能夠得出如下save和bgsave的對比區別:
save是同步持久化數據,而bgsave是異步持久化數據。
save
不會fork子進程,經過主進程持久化數據,會阻塞處理客戶端的請求,而bdsave
會fork
子進程持久化數據,同時還能夠處理客戶端請求,高效。
save不會消耗內存,而bgsave會消耗內存。
缺點: RDB持久化後的文件是緊湊的二進制文件,適合於備份、全量複製、大規模數據恢復的場景,對數據完整性和一致性要求不高,RDB會丟失最後一次快照的數據。
優勢: 開機的恢復數據快,寫入持久化文件快。
AOF持久化機制是以日誌的形式記錄Redis中的每一次的增刪改操做,不會記錄查詢操做,以文本的形式記錄,打開記錄的日誌文件就能夠查看操做記錄。
AOF是默認不開啓的,如果像開啓AOF,在以下圖的配置修改便可:
appendonly no
修改成
appendonly yes
便可開啓,在AOF中經過
appendfilename
配置生成的文件名,該文件名默認爲
appendonly.aof
,路徑也是經過dir配置的,這個於RDB的同樣,具體的配置信息以下圖所示:
AOF帶來的持久化更加安全可靠,默認提供三種觸發機制,以下所示:
no
:表示等操做系統等數據緩存同步到磁盤中(快、持久化沒保證)。
always
:同步持久化,每次發生數據變動時,就會當即記錄到磁盤中(慢,安全)。
everysec
:表示每秒同步一次(默認值,很快,可是會丟失一秒內的數據)。
AOF中每秒同步也是異步完成的,效率是很是高的,因爲該機制對日誌文件的寫入操做是採用append
的形式。
所以在寫入的過程即便宕機,也不會丟失已經存入日誌文件的數據,數據的完整性是很是高的。
在新安裝的Redis的配置文件中,AOF的配置以下所示:
可是,在寫入全部的操做到日誌文件中時,就會出現日誌文件不少重複的操做,甚至是無效的操做,致使日誌文件愈來愈大。
所謂的無效的的操做,舉個例子,好比某一時刻對一個k++,而後後面的某一時刻k--,這樣k的值是保持不變的,那麼這兩次的操做就是無效的。
若是像這樣的無效操做不少,記錄的文件臃腫,就浪費了資源空間,因此在Redis中出現了rewrite
機制。
redis提供了bgrewriteaof命令。將內存中的數據以命令的方式保存到臨時文件中,同時會fork出一條新進程來將文件重寫。
重寫AOF的日誌文件不是讀取舊的日誌文件瘦身,而是將內存中的數據用命令的方式重寫一個AOF文件,從新保存替換原來舊的日誌文件,所以內存中的數據纔是最新的。
重寫操做也會fork
一個子進程來處理重寫操做,重寫之內存中的數據做爲重寫的源,避免了操做的冗餘性,保證了數據的最新。
在Redis以append的形式將修改的數據寫入老的磁盤中 ,同時Redis也會建立一個新的文件用於記錄此期間有哪些命令被執行。
下面進行演示一下AOF的操做,首先先打開AOF機制,修改配置文件中的appendonly no
爲appendonly yes
,而後執行以下圖的操做:
appendonly.aof
key *
映射到該配置文件中的命令以下:
*2 //表示該命令兩組key 爲一組 * 爲一組
$6 //表示SELECT有6字符
SELECT
$1 //表示下面的0一個字符
0
而後執行set k1 1
的命令,此命令映射到文件中的命令以下:
*3 //表示該命令有三組set爲一組 k1爲一組 1爲一組
$3 // 表示set有三個字符
set // 表示執行了set命令
$2 // 表示k1有兩個字符
k1 // key值
$1 // 即是value值的字符長度爲1
1 // value值
當AOF的日誌文件增加到必定大小的時候Redis就可以bgrewriteaof對日誌文件進行重寫瘦身。當AOF配置文件大於改配置項時自動開啓重寫(這裏指超過原大小的100%)。
該配置能夠經過以下的配置項進行配置:
優勢: AOF更好保證數據不會被丟失,最多隻丟失一秒內的數據,經過foek一個子進程處理持久化操做,保證了主進程不會進程io操做,能高效的處理客戶端的請求。
另外重寫操做保證了數據的有效性,即便日誌文件過大也會進行重寫。
AOF的日誌文件的記錄可讀性很是的高,即便某一時刻有人執行flushall
清空了全部數據,只須要拿到aof的日誌文件,而後把最後一條的flushall給刪除掉,就能夠恢復數據。
缺點: 對於相同數量的數據集而言,AOF文件一般要大於RDB文件。RDB 在恢復大數據集時的速度比 AOF 的恢復速度要快。AOF在運行效率上每每會慢於RDB。
在redis4.0後混合持久化(RDB+AOF)對重寫的優化,4.0版本的混合持久化默認是關閉的,能夠經過如下的配置開啓混合持久化:
bgrewriteaof
來完成的,不一樣的是當開啓混合持久化時,fork出的子進程先將共享內存的數據以RDB方式寫入aof文件中,而後再將重寫緩衝區的增量命令以AOF方式寫入文件中。
寫入完成後通知主進程統計信息,並將新的含有RDB格式和AOF格式的AOF文件替換舊的AOF文件。簡單的說:新的AOF文件前半段是以RDB格式的全量數據後半段是AOF格式的增量數據。
優勢: 混合持久化結合RDB持久化和AOF持久化的優勢,因爲絕大部分的格式是RDB格式,加載速度快,增量數據以AOF方式保存,數據更少的丟失。
rdb適合大規模的數據恢復,因爲rdb時異快照的形式持久化數據,恢復的數據快,在必定的時間備份一次,而aof的保證數據更加完整,損失的數據只在秒內。
具體哪一種更適合生產,在官方的建議中兩種持久化機制同時開啓,若是兩種機制同時開啓,優先使用aof持久化機制。