什麼叫持久化?redis
用一句話能夠將持久化歸納爲:將數據(如內存中的對象)保存到可永久保存的存儲設備中。數據庫
持久化的主要應用是將內存中的對象存儲在數據庫中,或者存儲在磁盤文件中、 XML 數據文件中等等。vim
也能夠從以下兩個層面來理解持久化:緩存
Redis 爲何要持久化?安全
Redis 中的數據類型都支持 Push/Pop、Add/Remove 及取交集並集和差集及更豐富的操做,並且這些操做都是原子性的。服務器
在此基礎上,Redis 支持各類不一樣方式的排序。與 Memcached 同樣,爲了保證效率,數據都是緩存在內存中。架構
由於數據都是緩存在內存中的,當你重啓系統或者關閉系統後,緩存在內存中的數據都會消失殆盡,再也找不回來了。app
因此,爲了讓數據可以長期保存,就要將 Redis 放在緩存中的數據作持久化存儲。異步
Redis 怎麼實現持久化?函數
在設計之初,Redis 就已經考慮到了這個問題。官方提供了多種不一樣級別的數據持久化的方式:
Redis 還能對 AOF 文件進行後臺重寫,使得 AOF 文件的體積不至於過大。
若是你不知道該選擇哪個級別的持久化方式,那咱們就先來了解一下 AOF 方式和 RDB 方式有什麼樣的區別,而且它們各自有何優劣,學習完以後,再來考慮該選擇哪種級別。
RDB 方式與 AOF 方式的優點對比
RDB 方式與 AOF 方式的優勢對比
首先咱們來看一看官方對於兩種方式的優勢描述,並作個對比,而後再看一看兩種方式的缺點描述。
RDB 方式的優勢:
當 Redis 須要保存 dump.rdb 文件時, 服務器執行如下操做:
這種工做方式使得 Redis 能夠從寫時複製(copy-on-write)機制中獲益。
AOF 方式的優勢:
Redis 的性能依然很好( Fsync 是由後臺線程進行處理的,主線程會盡力處理客戶端請求),一旦出現故障,你最多丟失 1 秒的數據。
整個重寫操做是絕對安全的,由於 Redis 在建立新 AOF 文件的過程當中,會繼續將命令追加到現有的 AOF 文件裏面,即便重寫過程當中發生停機,現有的 AOF 文件也不會丟失。
而一旦新 AOF 文件建立完畢,Redis 就會從舊 AOF 文件切換到新 AOF 文件,並開始對新 AOF 文件進行追加操做。
所以 AOF 文件的內容很是容易被人讀懂, 對文件進行分析(parse)也很輕鬆。導出(export) AOF 文件也很是簡單。
舉個例子,若是你不當心執行了 FLUSHALL 命令,但只要 AOF 文件未被重寫,那麼只要中止服務器, 移除 AOF 文件末尾的 FLUSHALL 命令,並重啓 Redis ,就能夠將數據集恢復到 FLUSHALL 執行以前的狀態。
優勢對比總結:
能夠在某些須要的時候打開 AOF 文件對其編輯,增長或刪除某些記錄,最後再執行恢復操做。
RDB 方式與 AOF 方式的缺點對比
RDB 方式的缺點:
雖然你能夠配置不一樣的 Save 時間點(例如每隔 5 分鐘而且對數據集有 100 個寫的操做),可是 Redis 要完整的保存整個數據集是一個比較繁重的工做。
你一般會每隔 5 分鐘或者更久作一次完整的保存,萬一 Redis 意外宕機,你可能會丟失幾分鐘的數據。
若是數據集巨大而且 CPU 性能不是很好的狀況下,這種狀況會持續 1 秒,AOF 也須要 Fork,可是你能夠調節重寫日誌文件的頻率來提升數據集的耐久度。
AOF 方式的缺點:
不過在處理巨大的寫入載入時,RDB 能夠提供更有保證的最大延遲時間(Latency)。
缺點對比總結:
RDB 與 AOF 工做原理
AOF 重寫和 RDB 建立快照同樣,都巧妙地利用了寫時複製機制:
付諸實踐,RDB 與 AOF 的實現
RDB 方式持久化的開啓與配置
Redis 默認的持久化方式是 RDB ,而且默認是打開的。RDB 的保存方式分爲主動保存與被動保存。
主動保存能夠在 redis-cli 中輸入 Save 便可;被動保存須要知足配置文件中設定的觸發條件,目前官方默認的觸發條件能夠在 redis.conf 中看到:
save 900 1save 300 10save 60 10000
其含義爲:
服務器在900秒以內,對數據庫進行了至少1次修改。服務器在300秒以內,對數據庫進行了至少10次修改。服務器在60秒以內,對數據庫進行了至少10000次修改。
知足觸發條件後,數據就會被保存爲快照,正是由於這樣才說 RDB 的數據完整性是比不上 AOF 的。
觸發保存條件後,會在指定的目錄生成一個名爲 dump.rdb 的文件,等到下一次啓動 Redis 時,Redis 會去讀取該目錄下的 dump.rdb 文件,將裏面的數據恢復到 Redis。
這個目錄在哪裏呢?咱們能夠在客戶端中輸入命令 config get dir 查看:
返回結果中的"/home/gannicus/Documents/redis-5.0.0"就是存放 dump.rdb 的目錄。
在測試以前,說明一下前提:Redis 是直接從官網下載的壓縮包,解壓後獲得 redis-x.x.x 文件夾。
好比個人是 redis-5.0.0,而後進入文件夾,在 redis-5.0.0 項目根目錄使用 make 命令安裝。
RDB 被動觸發保存測試
剛纔提到它分爲主動保存與被動觸發,如今咱們來測試一下被動觸發。首先啓動 redis-server,而後再打開客戶端 redis-cli ,先增添幾條記錄:
127.0.0.1:6379> set lca 1OK127.0.0.1:6379> set lcb 1OK127.0.0.1:6379> set lcc 1OK127.0.0.1:6379> set lcd 1OK127.0.0.1:6379> set lce 1OK127.0.0.1:6379> set lcf 1OK127.0.0.1:6379> set lcg 1OK127.0.0.1:6379> set lch 1OK127.0.0.1:6379> set lci 1OK127.0.0.1:6379> set lcj 1OK127.0.0.1:6379> set lck 1OK127.0.0.1:6379> set lcl 1OK127.0.0.1:6379> set lcm 1OK
能夠看到,總共添加了 13 條記錄:
127.0.0.1:6379> keys * 1) "lca" 2) "lcd" 3) "lcg" 4) "lce" 5) "lcb" 6) "lcm" 7) "lcf" 8) "lci" 9) "lcl"10) "lcc"11) "lck"12) "lcj"13) "lch"127.0.0.1:6379>
而後發現 redis-server 端的日誌窗口中出現了以下的提示:
21971:M 21 Oct 2018 16:52:44.062 * 10 changes in 300 seconds. Saving...21971:M 21 Oct 2018 16:52:44.063 * Background saving started by pid 2255222552:C 21 Oct 2018 16:52:44.066 * DB saved on disk21971:M 21 Oct 2018 16:52:44.165 * Background saving terminated with success
從英文提示中能夠大概讀懂這些內容,它檢測到 300 秒內有 10 條記錄被改動,剛纔咱們添加了 13 條數據記錄,知足 redis.conf 中對於 RDB 數據保存的條件。
因此這裏執行數據保存操做,而且提示開闢了一個 22552 的進程出來執行保存操做,最後提示保存成功。而且在目錄內看到有 dump.rdb 文件生成。
如今將 Redis 進程 Kill,哪些數據會被保存?經過命令 kill -9 pid ( pid 是進程編號)模擬 Redis 異常關閉,而後再啓動 Redis 。
咱們來看一看,究竟是隻保存了 10 條記錄仍是 13 條全都保存下來了?
127.0.0.1:6379> keys * 1) "lcb" 2) "lcj" 3) "lcd" 4) "lch" 5) "lci" 6) "lcc" 7) "lcf" 8) "lce" 9) "lca"10) "lcg"127.0.0.1:6379>
重啓後查看記錄,發現 13 條記錄中只有 10 條記錄會被保存,這也印證了以前所說,RDB 方式的數據完整性是不可靠的,除非斷掉的那一刻正好是知足觸發條件的條數。
關閉 RDB
剛纔提到了,它是默認啓用的,若是你不須要它能夠在配置文件中將這 3 個配置註釋掉,並新增 save " " 便可:
保存配置文件後須要從新啓動 Redis 服務纔會生效,而後繼續添加十幾條記錄:
在以前已有 10 條的基礎上我再增長了 14 條記錄,此次一樣要經過 kill 來模擬 Redis 異常關閉,再啓動服務看一看,數據是否還被保存:
發現後面添加的 14 條記錄並無被保存,恢復數據的時候僅僅只是恢復了以前的 10 條。
而且觀察 Redis 服務端窗口日誌,並未發現像以前同樣的觸發保存的提示,證實 RDB 方式已經被關閉。
RDB 主動保存測試
經過配置文件關閉被動觸發,那麼主動關閉是否還會生效呢?
在 Redis 客戶端( redis-cli )經過 del 命令刪除幾條記錄,而後輸入 save 命令執行保存操做:
能夠看到 redis-server 的日誌有新的提示:22598:M 21 Oct 2018 17:22:31.365 * DB saved on disk,它告訴咱們數據已經保存。
那麼繼續模擬異常關閉,再打開服務,看一看是否真的保存了這些操做:
果不其然,這幾個刪除操做都被保存了下來,恢復過來的數據中已經沒有那 3 條記錄了,證實主動關閉不受配置文件的影響。除了 Save 還有其餘的保存方式麼?
Save 和 Bgsave 保存
有的,Redis 提供了 Save 和 Bgsave 這兩種不一樣的保存方式,而且這兩個方式在執行的時候都會調用 rdbSave 函數。
但它們調用的方式各有不一樣:
由於 rdbSave 在子進程被調用,因此 Redis 服務器在 Bgsave 執行期間仍然能夠繼續處理客戶端的請求。
Save 是同步操做,Bgsave 是異步操做。Bgsave 命令的使用方法和 Save 命令的使用方法是同樣的:
Shutdown 保存
事實上,Shutdown 命令也是能夠保存數據的,驚不驚喜。它會在關閉前將數據保存下來,意不意外?
而後 Redis 服務就被關閉掉了。咱們須要從新啓動 Redis 服務,到客戶端中看一看是否生效:
居然沒有生效,刺不刺激?這是爲何呢?明明官方文檔之 Shutdown 就說會保存了才退出的,你騙人~注意到,文檔中有一句:
恍然大悟,原來是要在持久化被打開的狀況下,經過 Shutdown 命令關閉纔不會丟失數據,那麼就到配置文件中將那幾個 Save 的配置項打開吧:
而後再開啓 Redis 服務,再嘗試一遍(過程爲:添加 -> shutdown -> 重啓服務 -> 查看):
這下終於弄明白了。
AOF 方式持久化的開啓與配置
開啓 AOF
默認是不開啓 AOF 的,若是想要啓用則須要到 redis.conf 配置文件中開啓,打開 redis.conf:
而後在文件中找到 appendonly 並將 no 改成 yes:
即爲開啓了 AOF 方式的持久化。
設置同步方式
AOF 還有支持幾種同步方式,它們分別是:
默認配置是 everysec,你能夠根據需求進行調整,這裏我將配置改爲 always:
自定義 AOF 記錄文件的文件名
Redis 設置有默認的文件名,在配置中顯示爲:
你可讓其保持默認名字,也能夠指定其餘的文件名,好比:
將 appendonly、appendfsync 和 appendfilename 設置好並保存。從新啓動 Redis 服務:
經過命令 ls 查看本地文件,能夠看到新生成了一個名爲 RNGLetme.aof 的文件,可使用:
來查看裏面的內容,因爲當前未進行數據的改動,因此是空白的。而後打開 Redis 的客戶端:
而且添加幾條數據記錄:
能夠看到,成功添加了 rng、edg、ig 這三條記錄,而後打開 RNGLetme.aof 文件,看看裏面的記錄:
每一次的數據添加都被記錄下來了。那若是是刪除操做呢,也會被記錄下來麼?
執行完刪除操做後,再看一看 RNGLetme.aof 文件中的記錄:
對比以前的記錄,新增了 del edg 的操做記錄。這就印證了以前對 AOF 的描述:以日誌的方式將數據變更記錄下來。
AOF 恢復測試
下面一樣是經過 Kill 命令模擬 Redis 異常關閉:
而後再從新啓動 Redis 服務:
接着經過客戶端看一看,那些數據是否都在:
能夠看到,rng 和 ig 都還在,意味着持久化是生效的。
怎樣從 RDB 方式切換爲 AOF 方式
在 Redis 2.2 或以上版本,能夠在不重啓的狀況下,從 RDB 切換到 AOF :
爲最新的 dump.rdb 文件建立一個備份、將備份放到一個安全的地方。
執行如下兩條命令:
確保寫命令會被正確地追加到 AOF 文件的末尾。執行的第一條命令開啓了 AOF 功能:Redis 會阻塞直到初始 AOF 文件建立完成爲止,以後 Redis 會繼續處理命令請求,並開始將寫入命令追加到 AOF 文件末尾。
執行的第二條命令用於關閉 RDB 功能。這一步是可選的,若是你願意的話,也能夠同時使用 RDB 和 AOF 這兩種持久化功能。
注意:別忘了在 redis.conf 中打開 AOF 功能!不然服務器重啓後,以前經過 CONFIG SET 命令設置的配置就會被遺忘,程序會按原來的配置來啓動服務器。
優先選擇 RDB 仍是 AOF 呢?
分析對比兩種方式並作了測試後,發現這是兩種不一樣風格的持久化方式。那麼應該如何選擇呢?
備份 Redis 數據的建議
確保你的數據有完整的備份,磁盤故障、節點失效等問題可能讓你的數據消失不見, 不進行備份是很是危險的。
Redis 對於數據備份是很是友好的,由於你能夠在服務器運行的時候對 RDB 文件進行復制:RDB 文件一旦被建立,就不會進行任何修改。
當服務器要建立一個新的 RDB 文件時,它先將文件的內容保存在一個臨時文件裏面,當臨時文件寫入完畢時,程序才使用 rename(2) 原子地用臨時文件替換原來的 RDB 文件。
這也就是說,不管什麼時候,複製 RDB 文件都是絕對安全的:
Redis 密碼持久化
在 Redis 中數據須要持久化,密碼也要持久化。在客戶端經過命令:
能夠爲 Redis 設置值爲 zxc9527 的密碼,可是當 Redis 關閉並從新啓動後,權限驗證功能就會失效,不再須要密碼。
因此,密碼也須要在 redis.conf 中持久化。打開 redis.conf 找到 requirepass 配置項,取消其註釋並在後面設置密碼:
保存後重啓 Redis 服務,密碼持久化即生效。