redis是一個基於內存的數據庫,故在redis正在運行的數據都在內存中,而內存掉電,內存上所以數據都會消失。故把redis當成數據庫使用時就需要對redis進行持久化。
在說redis持久化的時候,我們先來聊聊其他的知識。linux的父子進程。在Linux中使用fork()函數會給當前正在運行的進程創建一個子進程。那么現在問題就來了,fork時父子進程中的數據有什么關系呢?一般說到進程我們都會知道進程間彼此是數據隔離的。然而實際上,子進程在剛創建時,可以看到子進程中的數據。而在修改該數據時,卻不會對父進程造成影響。同樣子進程也不會受到父進程修改數據的影響。而造成這種現象的,正是因為linux的copy on write機制。
copy on write:是一種內核機制,通俗來講就是寫時復制。及創建子進程並不發生復制,創建子進程后父子進程共用數據。只有在修改數據是才會創建新的空間。
這樣做的好處是創建進程變快了。而且根據開發經驗,我們創建子進程后不可能父子進程把所有數據都改一遍。而這套機制就是指針支撐的。玩的是指針
redis中有兩種數據到存儲方式,rdb和aof。下面我們來着重講一下這兩種持久化方式:
1.RDB
rdb持久化的方式
RDB持久化方式能夠在指定的時間間隔能對你的數據進行快照存儲.
redis的rdb持久化方式有存儲的是時點數據即某一個時間點的數據。因為如果存儲實時更新的數據的話,如果一直有數據寫入會導致,持久化過程一直進行,降低了redis的快捷的特性。因此redis有兩種持久化數據的方式
- save:前台更新數據,如果使用這種方法持久化,那么只能在服務器停機維護時,發生因為它會阻塞redis進程造成redis的服務不可用。
- bgsave:后台運行,該命令的原理是,創建一個子進程來進行redis的持久化,而redis依然提供服務。此時就用到了剛才講到的copy on write機制,父子進程共用了一套數據。
以上兩個命令直接可以在redis的客戶端運行。
注意如果使用配置文件的方式配置數據持久化,配置文件中給出bgsave的規則: save這個標識。配置的規則:(要修改的文件是dbfilename dump.rdb,文件一般存儲在var/lib/redis/6379)
save 900 1
save 300 10
save 60 10000
該規則意味着,在每60秒檢測一次redis的數據量,如果達到10000就進行持久化,否則不持久化。在每300秒檢測一次redis的數據量,如果達到10就進行持久化,否則不持久化。在每900秒檢測一次redis的數據量,如果達到1就進行持久化,否則不持久化。
rdb方式的優點:
- RDB是一個非常緊湊的文件,它保存了某個時間點得數據集,非常適用於數據集的備份,比如你可以在每個小時報保存一下過去24小時內的數據,同時每天保存過去30天的數據,這樣即使出了問題你也可以根據需求恢復到不同版本的數據集.
- RDB是一個緊湊的單一文件,很方便傳送到另一個遠端數據中心或者亞馬遜的S3(可能加密),非常適用於災難恢復.
- RDB在保存RDB文件時父進程唯一需要做的就是fork出一個子進程,接下來的工作全部由子進程來做,父進程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的性能.
- 與AOF相比,在恢復大的數據集的時候,RDB方式會更快一些.
rdb的缺點
- 如果你希望在redis意外停止工作(例如電源中斷)的情況下丟失的數據最少的話,那么RDB不適合你.雖然你可以配置不同的save時間點(例如每隔5分鍾並且對數據集有100個寫的操作),是Redis要完整的保存整個數據集是一個比較繁重的工作,你通常會每隔5分鍾或者更久做一次完整的保存,萬一在Redis意外宕機,你可能會丟失幾分鍾的數據.
- RDB 需要經常fork子進程來保存數據集到硬盤上,當數據集比較大的時候,fork的過程是非常耗時的,可能會導致Redis在一些毫秒級內不能響應客戶端的請求.如果數據集巨大並且CPU性能不是很好的情況下,這種情況會持續1秒,AOF也需要fork,但是你可以調節重寫日志文件的頻率來提高數據集的耐久度.
- 不支持拉鏈化,只有一個rdb文件
- 丟失數據相對多一些時點與時點之間窗口數據容易丟失。8點得到一個rdb,9點剛要寫一個rdb,掛機了。那么8~9之間的數據就會丟失。
2.AOF
AOF實際是把對redis操作的操作記錄,通過日志的方式記錄下來,這樣想要恢復數據庫文件,只需要把所以指令執行一遍就行。
需要開啟aof只需要把dump修改appendonly該為yes即可。
appendonly yes
aof的優點
- 使用AOF 會讓你的Redis更加耐久: 你可以使用不同的fsync策略:無fsync,每秒fsync,每次寫的時候fsync.使用默認的每秒fsync策略,Redis的性能依然很好(fsync是由后台線程進行處理的,主線程會盡力處理客戶端請求),一旦出現故障,你最多丟失1秒的數據.
- AOF文件是一個只進行追加的日志文件,所以不需要寫入seek,即使由於某些原因(磁盤空間已滿,寫的過程中宕機等等)未執行完整的寫入命令,你也也可使用redis-check-aof工具修復這些問題.
- Redis 可以在 AOF 文件體積變得過大時,自動地在后台對 AOF 進行重寫: 重寫后的新 AOF 文件包含了恢復當前數據集所需的最小命令集合。 整個重寫操作是絕對安全的,因為 Redis 在創建新 AOF 文件的過程中,會繼續將命令追加到現有的 AOF 文件里面,即使重寫過程中發生停機,現有的 AOF 文件也不會丟失。 而一旦新 AOF 文件創建完畢,Redis 就會從舊 AOF 文件切換到新 AOF 文件,並開始對新 AOF 文件進行追加操作。
- AOF 文件有序地保存了對數據庫執行的所有寫入操作, 這些寫入操作以 Redis 協議的格式保存, 因此 AOF 文件的內容非常容易被人讀懂, 對文件進行分析(parse)也很輕松。 導出(export) AOF 文件也非常簡單: 舉個例子, 如果你不小心執行了 FLUSHALL 命令, 但只要 AOF 文件未被重寫, 那么只要停止服務器, 移除 AOF 文件末尾的 FLUSHALL 命令, 並重啟 Redis , 就可以將數據集恢復到 FLUSHALL 執行之前的狀態
aof的缺點
弊端,體量無線變大, 恢復慢
為解決aof的弊端日志,優點如果能保住,還是可以用的。就有一個方案:設計一個方案讓日志,AOF足夠小
就是hdfs,fsimage+edits.log 。讓日志只記錄增量,合並操作的中間過程。
而4.0版本也是這項技術的分界點
- 4.0以前進行重寫時,刪除抵消的命令合並重復的命令。這樣最終也是一個純指令的日志文件
- 4.0以后將老的數據RDB到aof文件中,將增量的以指令的方式Append到AOFAOF是一個混合體。其利用了RDB的快,利用了日志的全量
從這點可以看出,aof和rdb是可以共存的。
3.持久化的其他特性
日志重寫
Redis 支持一種有趣的特性: 可以在不打斷服務客戶端的情況下, 對 AOF 文件進行重建(rebuild)。執行 BGREWRITEAOF 命令, Redis 將生成一個新的 AOF 文件, 這個文件包含重建當前數據集所需的最少命令。Redis 2.2 需要自己手動執行 BGREWRITEAOF 命令; Redis 2.4 則可以自動觸發 AOF 重寫, 具體信息請查看 2.4 的示例配置文件。
工作原理
AOF 重寫和 RDB 創建快照一樣,都巧妙地利用了寫時復制機制:
- Redis 執行 fork() ,現在同時擁有父進程和子進程。子進程開始將新 AOF 文件的內容寫入到臨時文件。
- 對於所有新執行的寫入命令,父進程一邊將它們累積到一個內存緩存中,一邊將這些改動追加到現有 AOF 文件的末尾,這樣樣即使在重寫的中途發生停機,現有的 AOF 文件也還是安全的。
- 當子進程完成重寫工作時,它給父進程發送一個信號,父進程在接收到信號之后,將內存緩存中的所有數據追加到新 AOF 文件的末尾。
搞定!現在 Redis 原子地用新文件替換舊文件,之后所有命令都會直接追加到新 AOF 文件的末尾。
redis的持久化想要開啟其實挺簡單的只需要,修改conf配置文件的幾個配置項即可。
rdb和aof混合使用
當二者混合使用時,如果redis服務器停止后重新運行,那么redis恢復數據只會從aof中同步,而不會去向rdb同步。而且在主從復制時,rdb會記錄上一次連接的端口,而aof不會。所以主從復制時,如果沒有開啟aof,那么從服務器在斷開主服務器后重新連接主服務器,只會同步從服務器斷開時的增量數據,而開啟aof后從服務器需要同步主服務器中的所有內容。