Redis數據持久化
第1章 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 你甚至可以關閉持久化功能,讓數據只在服務器運行時存在。
第2章 RD--快照
2.1 RDB的優點
q RDB 是一個非常緊湊(compact)的文件,它保存了 Redis 在某個時間點上的數據集。 這種文件非常適合用於進行備份: 比如說,你可以在最近的 24 小時內,每小時備份一次 RDB 文件,並且在每個月的每一天,也備份一個 RDB 文件。 這樣的話,即使遇上問題,也可以隨時將數據集還原到不同的版本。
q RDB 非常適用於災難恢復(disaster recovery):它只有一個文件,並且內容都非常緊湊,可以(在加密後)將它傳送到別的數據中心。
q RDB 可以最大化 Redis 的性能:父進程在保存 RDB 文件時唯一要做的就是 fork 出一個子進程,然後這個子進程就會處理接下來的所有保存工作,父進程無須執行任何磁盤 I/O 操作。
q RDB 在恢復大數據集時的速度比 AOF 的恢復速度要快。
2.2 RDB的缺點
q 如果你需要儘量避免在服務器故障時丟失數據,那麼 RDB 不適合你。 雖然 Redis 允許你設置不同的保存點(save point)來控制保存 RDB 文件的頻率, 但是, 因爲RDB 文件需要保存整個數據集的狀態, 所以它並不是一個輕鬆的操作。 因此你可能會至少 5 分鐘才保存一次 RDB 文件。 在這種情況下, 一旦發生故障停機, 你就可能會丟失好幾分鐘的數據。
q 每次保存 RDB 的時候,Redis 都要 fork() 出一個子進程,並由子進程來進行實際的持久化工作。 在數據集比較龐大時, fork() 可能會非常耗時,造成服務器在某某毫秒內停止處理客戶端; 如果數據集非常巨大,並且 CPU 時間非常緊張的話,那麼這種停止時間甚至可能會長達整整一秒。 雖然 AOF 重寫也需要進行 fork() ,但無論 AOF 重寫的執行間隔有多長,數據的耐久性都不會有任何損失。
2.3 配置RDB快照
2.3.1 快照文件名
在默認的情況下, Redis 將數據庫快照保存在名字爲 dump.rdb 的二進制文件中。這是由參數dbfilename來決定的。
2.3.2 快照保存策略
以對 Redis 進行設置, 讓它在“ N 秒內數據集至少有 M 個改動”這一條件被滿足時, 自動保存一次數據集。
比如說, 以下設置會讓 Redis 在滿足“ 60 秒內有至少有 1000 個鍵被改動”這一條件時, 自動保存一次數據集:
save 60 1000
默認配置爲:
save 900 1 save 300 10 save 60 10000
如果想要關閉快照功能,則只需將以上配置替換爲:
save ""
2.4 RDB快照運作方式
當 Redis 需要保存 dump.rdb 文件時, 服務器執行以下操作:
Redis調用 fork() ,同時擁有父進程和子進程。
子進程將數據集寫入到一個臨時 RDB 文件中。
當子進程完成對新 RDB 文件的寫入時,Redis 用新 RDB 文件替換原來的 RDB 文件,並刪除舊的 RDB 文件。
第3章 AOF--追加
3.1 AOF的優點
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 執行之前的狀態。
3.2 AOF的缺點
q 對於相同的數據集來說,AOF 文件的體積通常要大於 RDB 文件的體積。
q 根據所使用的 fsync 策略,AOF 的速度可能會慢於 RDB 。 在一般情況下, 每秒 fsync 的性能依然非常高, 而關閉 fsync 可以讓 AOF 的速度和 RDB 一樣快, 即使在高負荷之下也是如此。 不過在處理巨大的寫入載入時,RDB 可以提供更有保證的最大延遲時間(latency)。
q AOF 在過去曾經發生過這樣的 bug : 因爲個別命令的原因,導致 AOF 文件在重新載入時,無法將數據集恢復成保存時的原樣。 (舉個例子,阻塞命令 BRPOPLPUSH 就曾經引起過這樣的 bug 。) 測試套件裏爲這種情況添加了測試: 它們會自動生成隨機的、複雜的數據集, 並通過重新載入這些數據來確保一切正常。 雖然這種 bug 在 AOF 文件中並不常見, 但是對比來說, RDB 幾乎是不可能出現這種 bug 的。
3.3 配置AOF
3.3.1 AOF功能開啓
通過修改配置文件來打開AOF功能:
appendonly yes
3.3.2 AOF同步策略
我們可以配置 Redis 多久纔將數據 fsync 到磁盤一次。
有三個選項:
q always
每次有新命令追加到 AOF 文件時就執行一次 fsync :非常慢,也非常安全。
q everysec
每秒 fsync 一次:足夠快(和使用 RDB 持久化差不多),並且在故障時只會丟失 1 秒鐘的數據。推薦(並且也是默認)的措施爲每秒 fsync 一次, 這種 fsync 策略可以兼顧速度和安全性
q no
從不 fsync :將數據交給操作系統來處理。更快,也更不安全的選擇。
具體參數如下:
appendfsync everysec
3.3.3 AOF重寫
因爲 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文件的最小大小
3.3.4 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才能啓動服務。
3.3.5 AOF運作方式
AOF 重寫和 RDB 創建快照一樣,都巧妙地利用了寫時複製機制。
以下是 AOF 重寫的執行步驟:
1、Redis 執行 fork() ,現在同時擁有父進程和子進程。
2、子進程開始將新 AOF 文件的內容寫入到臨時文件。
3、對於所有新執行的寫入命令,父進程一邊將它們累積到一個內存緩存中,一邊將這些改動追加到現有 AOF 文件的末尾: 這樣即使在重寫的中途發生停機,現有的 AOF 文件也還是安全的。
4、當子進程完成重寫工作時,它給父進程發送一個信號,父進程在接收到信號之後,將內存緩存中的所有數據追加到新 AOF 文件的末尾。
5、搞定!現在 Redis 原子地用新文件替換舊文件,之後所有命令都會直接追加到新 AOF 文件的末尾。
第4章 RDB和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 設置的配置就會被遺忘, 程序會按原來的配置來啓動服務器。