1、前言redis
因爲Redis的數據都存放在內存中,若是沒有配置持久化,redis重啓後數據就全丟失了,因而須要開啓redis的持久化功能,將數據保存到磁盤上,當redis重啓後,能夠從磁盤中恢復數據。數據庫
Redis提供兩種方式進行持久化,緩存
一種是RDB()持久化(原理是將Reids在內存中的數據庫記錄定時dump到磁盤上的RDB持久化),安全
另一種是AOF(append-only file)持久化(原理是將Reids的操做日誌以追加的方式寫入文件)。服務器
2、Redis 持久化app
Redis 提供了不一樣級別的持久化方式:工具
RDB持久化方式可以在指定的時間間隔能對你的數據進行快照存儲性能
AOF持久化方式記錄每次對服務器寫的操做,當服務器重啓的時候會從新執行這些命令來恢復原始的數據,AOF命令以redis協議追加保存每次寫的操做到文件末尾.Redis還能對AOF文件進行後臺重寫,使得AOF文件的體積不至於過大ui
若是你只但願你的數據在服務器運行的時候存在,你也能夠不使用任何持久化方式.加密
你也能夠同時開啓兩種持久化方式, 在這種狀況下, 當redis重啓的時候會優先載入AOF文件來恢復原始的數據,由於在一般狀況下AOF文件保存的數據集要比RDB文件保存的數據集要完整.
最重要的事情是瞭解RDB和AOF持久化方式的不一樣,讓咱們以RDB持久化方式開始:
RDB的優勢
RDB是一個很是緊湊的文件,它保存了某個時間點的數據集,很是適用於數據集的備份,好比你能夠在每一個小時保存一下過去24小時內的數據,同時天天保存過去30天的數據,這樣即便出了問題你也能夠根據需求恢復到不一樣版本的數據集
因爲RDB是一個緊湊的單一文件,很方便傳送到另外一個遠端數據中心或者Amazon 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,可是你能夠調節重寫日誌文件的頻率來提升數據集的耐久度。
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文件的體積一般要大於RDB文件的體積。
根據所使用的fsync策略,AOF的速度可能會慢於RDB。
在通常狀況下,每秒fsync的性能依然很是高而關閉fsync可讓AOF的速度和RDB同樣快,即便在高負荷之下也是如此。不過在處理巨大的寫入載入時,RDB能夠提供更有保證的最大延遲時間(latency)。
3、如何選擇使用哪一種持久化方式?
通常來講,若是想達到足以媲美PostgreSQL的數據安全性,你應該同時使用兩種持久化功能。
若是你很是關心你的數據,但仍然能夠承受數分鐘之內的數據丟失,那麼你能夠只使用RDB持久化。
有不少用戶都只使用AOF持久化,但咱們並不推薦這種方式: 由於定時生成 RDB 快照(snapshot)很是便於進行數據庫備份,而且RDB恢復數據集的速度也要比AOF恢復的速度要快,除此以外,使用RDB還能夠避免以前提到的AOF程序的bug。
Note: 由於以上提到的種種緣由,將來咱們可能會將AOF和RDB整合成單個持久化模型。
快照
在默認狀況下,Redis將數據庫快照保存在名字爲dump.rdb的二進制文件中。你能夠對Redis進行設置,讓它在「N秒內數據集至少有M個改動」這一條件被知足時,自動保存一次數據集。你也能夠經過調用SAVE或者BGSAVE,手動讓Redis進行數據集保存操做。
好比說,如下設置會讓Redis在知足「60秒內有至少有1000個鍵被改動」這一條件時,自動保存一次數據集:
save 60 1000
這種持久化方式被稱爲快照 snapshotting.
工做方式
當Redis須要保存dump.rdb文件時,服務器執行如下操做:
Redis調用fork(),同時擁有父進程和子進程。
子進程將數據集寫入到一個臨時RDB文件中。
當子進程完成對新RDB文件的寫入時,Redis用新RDB文件替換原來的RDB文件,並刪除舊的RDB文件。
這種工做方式使得Redis能夠從寫時複製(copy-on-write)機制中獲益。
只追加操做的文件(AOF)
快照功能並非很是耐久(durable): 若是Redis由於某些緣由而形成故障停機,那麼服務器將丟失最近寫入、且仍未保存到快照中的那些數據。 從1.1版本開始,Redis增長了一種徹底耐久的持久化方式:AOF持久化。
你能夠在配置文件中打開AOF方式:
appendonly yes
從如今開始,每當Redis執行一個改變數據集的命令時(好比 SET),這個命令就會被追加到AOF文件的末尾。這樣的話,當Redis從新啓時,程序就能夠經過從新執行AOF文件中的命令來達到重建數據集的目的。
日誌重寫
由於AOF的運做方式是不斷地將命令追加到文件的末尾,因此隨着寫入命令的不斷增長,AOF文件的體積也會變得愈來愈大。
舉個例子,若是你對一個計數器調用了100次INCR ,那麼僅僅是爲了保存這個計數器的當前值,AOF文件就須要使用100條記錄(entry)。然而在實際上,只使用一條SET命令已經足以保存計數器的當前值了,其他99條記錄實際上都是多餘的。
爲了處理這種狀況,Redis支持一種有趣的特性:能夠在不打斷服務客戶端的狀況下,對AOF文件進行重建(rebuild)。
執行BGREWRITEAOF命令,Redis將生成一個新的AOF文件,這個文件包含重建當前數據集所需的最少命令。
Redis 2.2須要本身手動執行 BGREWRITEAOF 命令;
Redis 2.4則能夠自動觸發AOF重寫,具體信息請查看2.4的示例配置文件。
AOF有多耐久性?
你能夠配置Redis多久纔將數據fsync到磁盤一次。有三種方式:
每次有新命令追加到AOF文件時就執行一次fsync:很是慢,也很是安全。
每秒fsync一次:足夠快(和使用RDB 持久化差很少),而且在故障時只會丟失1秒鐘的數據。
從不fsync:將數據交給操做系統來處理。更快,也更不安全的選擇。
推薦(而且也是默認)的措施爲每秒fsync 一次, 這種fsync策略能夠兼顧速度和安全性。
4、若是AOF文件損壞了怎麼辦?
服務器可能在程序正在對AOF文件進行寫入時停機,若是停機形成了AOF文件出錯(corrupt), 那麼Redis在重啓時會拒絕載入這個AOF文件,從而確保數據的一致性不會被破壞。當發生這種狀況時,能夠用如下方法來修復出錯的AOF文件:
爲現有的AOF文件建立一個備份。
使用Redis附帶的redis-check-aof程序,對原來的AOF文件進行修復:$ redis-check-aof –fix
使用diff -u對比修復後的AOF文件和原始AOF文件的備份,查看兩個文件之間的不一樣之處。(可選)
重啓Redis服務器,等待服務器載入修復後的AOF文件,並進行數據恢復。
工做原理
AOF重寫和RDB建立快照同樣,都巧妙地利用了寫時複製機制:
Redis執行fork(),如今同時擁有父進程和子進程。
子進程開始將新AOF文件的內容寫入到臨時文件。
對於全部新執行的寫入命令,父進程一邊將它們累積到一個內存緩存中,一邊將這些改動追加到現有AOF文件的末尾,這樣即便在重寫的中途發生停機,現有的AOF文件也仍是安全的。
當子進程完成重寫工做時,它給父進程發送一個信號,父進程在接收到信號以後,將內存緩存中的全部數據追加到新AOF文件的末尾。
如今Redis原子地用新文件替換舊文件,以後全部命令都會直接追加到新AOF文件的末尾。
5、怎樣從RDB方式切換爲AOF方式
在Redis 2.2或以上版本,能夠在不重啓的狀況下,從RDB切換到 AOF :
爲最新的dump.rdb文件建立一個備份。
將備份放到一個安全的地方。
執行如下兩條命令:
redis-cli config set appendonly yes
redis-cli config set save 「」
確保寫命令會被正確地追加到AOF文件的末尾。
執行的第一條命令開啓了AOF功能: Redis會阻塞直到初始AOF文件建立完成爲止,以後Redis會繼續處理命令請求,並開始將寫入命令追加到AOF文件末尾。
執行的第二條命令用於關閉RDB功能。這一步是可選的,若是你願意的話,也能夠同時使用RDB和AOF這兩種持久化功能。
重要:別忘了在 redis.conf 中打開AOF功能! 不然的話服務器重啓以後,以前經過CONFIG SET設置的配置就會被遺忘,程序會按原來的配置來啓動服務器。
6、AOF和RDB之間的相互做用
在2.4及以上版本的Redis中,BGSAVE執行的過程當中,不能夠執行BGREWRITEAOF。 反過來講,在BGREWRITEAOF執行的過程當中,也不能夠執行 BGSAVE。這能夠防止兩個Redis後臺進程同時對磁盤進行大量的I/O操做。
若是BGSAVE正在執行,而且用戶顯示地調用BGREWRITEAO 命令,那麼服務器將向用戶回覆一個OK狀態,並告知用戶,BGREWRITEAOF已經被預約執行: 一旦BGSAVE執行完畢,BGREWRITEAOF就會正式開始。
當Redis啓動時,若是RDB持久化和AOF持久化都被打開了,那麼程序會優先使用AOF文件來恢復數據集,由於AOF文件所保存的數據一般是最完整的。
7、備份redis數據
請牢記下面這句話:確保你的數據由完整的備份。磁盤故障、節點失效諸如此類的問題均可能讓你的數據消失不見,不進行備份是很是危險的。
Redis對於數據備份是很是友好的,由於你能夠在服務器運行的時候對RDB文件進行復制: RDB文件一旦被建立,就不會進行任何修改。當服務器要建立一個新的RDB文件時,它先將文件的內容保存在一個臨時文件裏面,當臨時文件寫入完畢時,程序才使用 rename(2) 原子地用臨時文件替換原來的RDB文件。
這也就是說,不管什麼時候,複製RDB文件都是絕對安全的。
建立一個按期任務(cron job), 每小時將一個RDB文件備份到一個文件夾,而且天天將一個RDB文件備份到另外一個文件夾。
確保快照的備份都帶有相應的日期和時間信息,每次執行按期任務腳本時,使用find命令來刪除過時的快照。好比說, 你能夠保留最近48 小時內的每小時快照,還能夠保留最近一兩個月的每日快照。
至少天天一次,將RDB備份到你的數據中心以外,或者至少是備份到你運行Redis服務器的物理機器以外。
8、經常使用配置
一、RDB持久化配置
Redis會將數據集的快照dump到dump.rdb文件中。此外,咱們也能夠經過配置文件來修改Redis服務器dump快照的頻率,在打開6379.conf文件以後,咱們搜索save,能夠看到下面的配置持久化策略:
save 900 1 #在900秒(15分鐘)以後,若是至少有1個key發生變化,則dump內存快照。
save 300 10 #在300秒(5分鐘)以後,若是至少有10個key發生變化,則dump內存快照。
save 60 10000 #在60秒(1分鐘)以後,若是至少有10000個key發生變化,則dump內存快照。
二、AOF持久化配置
在Redis的配置文件中存在三種同步方式,它們分別是:
appendfsync always #每次有數據修改發生時都會寫入AOF文件。
appendfsync everysec #每秒鐘同步一次,該策略爲AOF的缺省策略。
appendfsync no #從不一樣步。高效可是數據不會被持久化。
總結
RDB持久化是指在指定的時間間隔內將內存中的數據集快照寫入磁盤,實際操做過程是fork一個子進程,先將數據集寫入臨時文件,寫入成功後,再替換以前的文件,用二進制壓縮存儲。
AOF持久化以日誌的形式記錄服務器所處理的每個寫、刪除操做,查詢操做不會記錄,以文本的方式記錄,能夠打開文件看到詳細的操做記錄。
參考
Redis https://redis.io/topics/persistence
--EOF--