Redis數據持久化html
Redis 提供了多種不一樣級別的持久化方式:redis
q RDB 持久化能夠在指定的時間間隔內生成數據集的時間點快照(point-in-time snapshot)。數據庫
q AOF 持久化記錄服務器執行的全部寫操做命令,並在服務器啓動時,經過從新執行這些命令來還原數據集。 AOF 文件中的命令所有以 Redis 協議的格式來保存,新命令會被追加到文件的末尾。 Redis 還能夠在後臺對 AOF 文件進行重寫(rewrite),使得 AOF 文件的體積不會超出保存數據集狀態所需的實際大小。緩存
q Redis 還能夠同時使用 AOF 持久化和 RDB 持久化。 在這種狀況下, 當 Redis 重啓時, 它會優先使用 AOF 文件來還原數據集, 由於 AOF 文件保存的數據集一般比 RDB 文件所保存的數據集更完整。安全
q 你甚至能夠關閉持久化功能,讓數據只在服務器運行時存在。bash
q RDB 是一個很是緊湊(compact)的文件,它保存了 Redis 在某個時間點上的數據集。 這種文件很是適合用於進行備份: 好比說,你能夠在最近的 24 小時內,每小時備份一次 RDB 文件,而且在每月的每一天,也備份一個 RDB 文件。 這樣的話,即便趕上問題,也能夠隨時將數據集還原到不一樣的版本。服務器
q RDB 很是適用於災難恢復(disaster recovery):它只有一個文件,而且內容都很是緊湊,能夠(在加密後)將它傳送到別的數據中心。app
q RDB 能夠最大化 Redis 的性能:父進程在保存 RDB 文件時惟一要作的就是 fork 出一個子進程,而後這個子進程就會處理接下來的全部保存工做,父進程無須執行任何磁盤 I/O 操做。ide
q RDB 在恢復大數據集時的速度比 AOF 的恢復速度要快。工具
q 若是你須要儘可能避免在服務器故障時丟失數據,那麼 RDB 不適合你。 雖然 Redis 容許你設置不一樣的保存點(save point)來控制保存 RDB 文件的頻率, 可是, 由於RDB 文件須要保存整個數據集的狀態, 因此它並非一個輕鬆的操做。 所以你可能會至少 5 分鐘才保存一次 RDB 文件。 在這種狀況下, 一旦發生故障停機, 你就可能會丟失好幾分鐘的數據。
q 每次保存 RDB 的時候,Redis 都要 fork() 出一個子進程,並由子進程來進行實際的持久化工做。 在數據集比較龐大時, fork() 可能會很是耗時,形成服務器在某某毫秒內中止處理客戶端; 若是數據集很是巨大,而且 CPU 時間很是緊張的話,那麼這種中止時間甚至可能會長達整整一秒。 雖然 AOF 重寫也須要進行 fork() ,但不管 AOF 重寫的執行間隔有多長,數據的耐久性都不會有任何損失。
在默認的狀況下, Redis 將數據庫快照保存在名字爲 dump.rdb 的二進制文件中。這是由參數dbfilename來決定的。
以對 Redis 進行設置, 讓它在「 N 秒內數據集至少有 M 個改動」這一條件被知足時, 自動保存一次數據集。
好比說, 如下設置會讓 Redis 在知足「 60 秒內有至少有 1000 個鍵被改動」這一條件時, 自動保存一次數據集:
save 60 1000
默認配置爲:
save 900 1 save 300 10 save 60 10000
若是想要關閉快照功能,則只需將以上配置替換爲:
save ""
當 Redis 須要保存 dump.rdb 文件時, 服務器執行如下操做:
Redis調用 fork() ,同時擁有父進程和子進程。
子進程將數據集寫入到一個臨時 RDB 文件中。
當子進程完成對新 RDB 文件的寫入時,Redis 用新 RDB 文件替換原來的 RDB 文件,並刪除舊的 RDB 文件。
q 使用 AOF 持久化會讓 Redis 變得很是耐久(much more durable):你能夠設置不一樣的 fsync 策略,好比無 fsync ,每秒鐘一次 fsync ,或者每次執行寫入命令時 fsync 。 AOF 的默認策略爲每秒鐘 fsync 一次,在這種配置下,Redis 仍然能夠保持良好的性能,而且就算髮生故障停機,也最多隻會丟失一秒鐘的數據( fsync 會在後臺線程執行,因此主線程能夠繼續努力地處理命令請求)。
q AOF 文件是一個只進行追加操做的日誌文件(append only log), 所以對 AOF 文件的寫入不須要進行 seek , 即便日誌由於某些緣由而包含了未寫入完整的命令(好比寫入時磁盤已滿,寫入中途停機,等等), redis-check-aof 工具也能夠輕易地修復這種問題。
q Redis 能夠在 AOF 文件體積變得過大時,自動地在後臺對 AOF 進行重寫: 重寫後的新 AOF 文件包含了恢復當前數據集所需的最小命令集合。 整個重寫操做是絕對安全的,由於 Redis 在建立新 AOF 文件的過程當中,會繼續將命令追加到現有的 AOF 文件裏面,即便重寫過程當中發生停機,現有的 AOF 文件也不會丟失。 而一旦新 AOF 文件建立完畢,Redis 就會從舊 AOF 文件切換到新 AOF 文件,並開始對新 AOF 文件進行追加操做。
q AOF 文件有序地保存了對數據庫執行的全部寫入操做, 這些寫入操做以 Redis 協議的格式保存, 所以 AOF 文件的內容很是容易被人讀懂, 對文件進行分析(parse)也很輕鬆。 導出(export) AOF 文件也很是簡單: 舉個例子, 若是你不當心執行了 FLUSHALL 命令, 但只要 AOF 文件未被重寫, 那麼只要中止服務器, 移除 AOF 文件末尾的 FLUSHALL 命令, 並重啓 Redis , 就能夠將數據集恢復到 FLUSHALL 執行以前的狀態。
q 對於相同的數據集來講,AOF 文件的體積一般要大於 RDB 文件的體積。
q 根據所使用的 fsync 策略,AOF 的速度可能會慢於 RDB 。 在通常狀況下, 每秒 fsync 的性能依然很是高, 而關閉 fsync 可讓 AOF 的速度和 RDB 同樣快, 即便在高負荷之下也是如此。 不過在處理巨大的寫入載入時,RDB 能夠提供更有保證的最大延遲時間(latency)。
q AOF 在過去曾經發生過這樣的 bug : 由於個別命令的緣由,致使 AOF 文件在從新載入時,沒法將數據集恢復成保存時的原樣。 (舉個例子,阻塞命令 BRPOPLPUSH 就曾經引發過這樣的 bug 。) 測試套件裏爲這種狀況添加了測試: 它們會自動生成隨機的、複雜的數據集, 並經過從新載入這些數據來確保一切正常。 雖然這種 bug 在 AOF 文件中並不常見, 可是對比來講, RDB 幾乎是不可能出現這種 bug 的。
經過修改配置文件來打開AOF功能:
appendonly yes
咱們能夠配置 Redis 多久纔將數據 fsync 到磁盤一次。
有三個選項:
q always
每次有新命令追加到 AOF 文件時就執行一次 fsync :很是慢,也很是安全。
q everysec
每秒 fsync 一次:足夠快(和使用 RDB 持久化差很少),而且在故障時只會丟失 1 秒鐘的數據。推薦(而且也是默認)的措施爲每秒 fsync 一次, 這種 fsync 策略能夠兼顧速度和安全性
q no
從不 fsync :將數據交給操做系統來處理。更快,也更不安全的選擇。
具體參數以下:
appendfsync everysec
由於 AOF 的運做方式是不斷地將命令追加到文件的末尾, 因此隨着寫入命令的不斷增長, AOF 文件的體積也會變得愈來愈大。舉個例子, 若是你對一個計數器調用了 100 次 INCR , 那麼僅僅是爲了保存這個計數器的當前值, AOF 文件就須要使用 100 條記錄(entry)。然而在實際上, 只使用一條 SET 命令已經足以保存計數器的當前值了, 其他 99 條記錄實際上都是多餘的。
爲了處理這種狀況, Redis 支持一種有趣的特性: 能夠在不打斷服務客戶端的狀況下, 對 AOF 文件進行重建(rebuild)。執行 BGREWRITEAOF 命令, Redis 將生成一個新的 AOF 文件, 這個文件包含重建當前數據集所需的最少命令。
auto-aof-rewrite-percentage 100
#<==觸發自動重寫所佔的百分比,0表示禁用自動重寫功能
auto-aof-rewrite-min-size 64mb
#<==指定自動重寫AOF文件的最小大小
服務器可能在程序正在對 AOF 文件進行寫入時停機, 若是停機形成了 AOF 文件出錯(corrupt), 那麼 Redis 在重啓時會拒絕載入這個 AOF 文件, 從而確保數據的一致性不會被破壞。
當發生這種狀況時, 能夠用如下方法來修復出錯的 AOF 文件:
1、爲現有的 AOF 文件建立一個備份。
2、使用 Redis 附帶的 redis-check-aof 程序,對原來的 AOF 文件進行修復。
$ redis-check-aof --fix
3、(可選)使用 diff -u 對比修復後的 AOF 文件和原始 AOF 文件的備份,查看兩個文件之間的不一樣之處。
4、重啓 Redis 服務器,等待服務器載入修復後的 AOF 文件,並進行數據恢復。
配置參數以下:
aof-load-truncated yes
#<==是否加載被截斷(reids出問題時AOF文件可能被截斷)的AOF日誌。設置yes表示加載被截斷的AOF文件,並經過日誌告知用戶;若是設置爲no,則redis拒絕啓動,須要運行redis-check-aof才能啓動服務。
AOF 重寫和 RDB 建立快照同樣,都巧妙地利用了寫時複製機制。
如下是 AOF 重寫的執行步驟:
1、Redis 執行 fork() ,如今同時擁有父進程和子進程。
2、子進程開始將新 AOF 文件的內容寫入到臨時文件。
3、對於全部新執行的寫入命令,父進程一邊將它們累積到一個內存緩存中,一邊將這些改動追加到現有 AOF 文件的末尾: 這樣即便在重寫的中途發生停機,現有的 AOF 文件也仍是安全的。
4、當子進程完成重寫工做時,它給父進程發送一個信號,父進程在接收到信號以後,將內存緩存中的全部數據追加到新 AOF 文件的末尾。
5、搞定!如今 Redis 原子地用新文件替換舊文件,以後全部命令都會直接追加到新 AOF 文件的末尾。
在 Redis 2.2 或以上版本,能夠在不重啓的狀況下,從 RDB 切換到 AOF :
1、爲最新的 dump.rdb 文件建立一個備份。
2、將備份放到一個安全的地方。
3、執行如下兩條命令:
redis-cli> CONFIG SET appendonly yes redis-cli> CONFIG SET save ""
4、確保命令執行以後,數據庫的鍵的數量沒有改變。
5、確保寫命令會被正確地追加到 AOF 文件的末尾。
步驟 3 執行的第一條命令開啓了 AOF 功能: Redis 會阻塞直到初始 AOF 文件建立完成爲止, 以後 Redis 會繼續處理命令請求, 並開始將寫入命令追加到 AOF 文件末尾。
步驟 3 執行的第二條命令用於關閉 RDB 功能。 這一步是可選的, 也能夠同時使用 RDB 和 AOF 這兩種持久化功能。
注:別忘了在 redis.conf 中打開 AOF 功能! 不然的話, 服務器重啓以後, 以前經過 CONFIG SET 設置的配置就會被遺忘, 程序會按原來的配置來啓動服務器。