Redis 持久化(persistence)技術口袋書

本文首發於 Redis 持久化(persistence)技術口袋書,轉載請註明出處。

本文講解 Redis 數據庫的數據持久化解決方案。php

測試環境:html

RDB 和 AOF 持久化解決方案

Redis 提供兩種持久化解決方案:RDB 持久化和 AOF 持久化。git

要點:github

RDB 持久化:能夠在指定時間間隔內,生成數據集在這個時間點的快照。
AOF 持久化:經過記錄服務器執行的全部寫操做命令,在服務器重啓時,經過從新執行這些命令來還原數據。redis

RDB 持久化方案

採用 RDB 持久化方案時,Redis 會每隔一段時間對數據集進行快照備份,換句話說這種方案在服務器發生故障時可能形成數據的丟失。因此,若是對數據的完整性有比較強烈的要求,可能不太適用這種備份方案,即它適用於作數據的備份。shell

執行持久化策略

  • 自動執行 RDB 持久化

咱們已經知道,採用 RDB 持久化方案會每隔一段時間對數據進行備份,那麼這個時間段如何肯定呢?數據庫

咱們能夠到 redis.windows.conf 配置文件的 SNAPSHOTTING 配置節點獲取答案,默認狀況下 Redis 採用三種持久化策略:windows

save 900 1
save 300 10
save 60 10000

這裏的 save 指令表示「在 x 秒內有 n 個及以上鍵被改動」則會自動保存一次數據集,好比配置中的 save 60 10000 表示若是在 60 秒內有 10000 個及以上的鍵被改動時則執行保存數據集操做。緩存

咱們在啓動 Redis 服務時,服務器會讀取配置文件中的配置,因此 RDB 持久化策略會自動啓動,當知足條件時會執行持久化處理。安全

  • 手動執行 RDB 持久化

不過,有時咱們可能須要手動的執行 RDB 持久化處理,那麼 Redis 有沒有提供相似的方法呢?

答案是有的,咱們可使用 [SAVE]](http://redisdoc.com/server/sa...(這裏不是配置文件中的 save 指令)BGSAVE 命令,來手動執行 RDB 持久化處理。

雖然,savebgsave 均可以手動的執行 RDB 持久化處理。可是它們的工做模式徹底不一樣。

  1. 執行 SAVE 命令時,會阻塞 Redis 主進程,直到保存完成爲止。在主進程阻塞期間,服務器不能處理客戶端的任何請求。
  2. BGSAVE 則 fork 出一個子進程,子進程負責執行保存處理,並在保存完成以後向主進程發送信號,通知主進程保存完成。因此 Redis 服務器在 BGSAVE 執行期間仍然能夠繼續處理客戶端的請求。
注意:雖然經過 SAVE 命令能夠執行 RDB 持久化處理,可是它的運行原理同自動持久化中的 save 指令是徹底不一樣的, save 指令的工做原理同 BGSAVE 指令。

快照(SNAPSHOTTING)

在 RDB 持久化策略中,咱們引入了「快照」的概念,即「在 x 秒內有 n 個及以上鍵被改動」則執行持久化處理。

寫時複製(copy-on-write):快照的運行原理

  1. Redis 調用 fork() ,同時擁有父進程和子進程。
  2. 子進程將數據集寫入到一個臨時 RDB 文件中。
  3. 當子進程完成對新 RDB 文件的寫入時,Redis 用新 RDB 文件替換原來的 RDB 文件,並刪除舊的 RDB 文件。

摘自 Redis 持久化

優勢

  • RDB 是一個很是緊湊(compact)的文件(筆者注:由於 RDB 持久化文件 dump.rdb 將數據集以二級制形式保存),它保存了 Redis 在某個時間點上的數據集。 這種文件很是適合用於進行備份。
  • RDB 很是適用於災難恢復(disaster recovery):它只有一個文件,而且內容都很是緊湊,能夠(在加密後)將它傳送到別的數據中心,或者亞馬遜 S3 中。
  • RDB 能夠最大化 Redis 的性能:父進程在保存 RDB 文件時惟一要作的就是 fork 出一個子進程,而後這個子進程就會處理接下來的全部保存工做,父進程無須執行任何磁盤 I/O 操做。
  • RDB 在恢復大數據集時的速度比 AOF 的恢復速度要快。

缺點

  • 可能在服務器故障時致使數據丟失,由於 RDB 採用的是定時保存數據的機制,因此可能致使下次保存數據時的數據丟失。
  • 可能致使服務器沒法處理客戶端處理,這是因爲 RDB 執行非阻塞(BGSAVE 或 save 指令)保存時,會 fock 出子進程,若是待保存的數據集很是大可能會很是耗時。

AOF 持久化方案

經過 RDB 持久化方案的學習,咱們知道它可能致使數據丟失,若是你的項目忍不了數據丟失的問題,那麼可能就須要使用 AOF 持久化方案。

AOF(append only file):只進行追加操做的文件。默認狀況下,Redis 會禁用 AOF 重寫,無需開啓咱們須要到配置文件中將 appendonly 指令配置爲 yes(默認:no 不啓用)

啓用 AOF 持久化方案後,當咱們執行相似 SET 設置(或修改)命令時,Redis 會將命令以 Redis 通訊協議 文本保存到 appendonly.aof 文件中。

執行持久化策略

AOF 持久化方案提供 3 種不一樣時間策略將數據同步到磁盤中,同步策略經過 appendfsync 指令完成:

  • everysec(默認):表示每秒執行一次 fsync 同步策略,效率上同 RDB 持久化差很少。因爲每秒同步一次,因此服務器故障時會丟失 1 秒內的數據。
  • always: 每一個寫命令都會調用 fsync 進行數據同步,最安全但影響性能。
  • no: 表示 Redis 從不執行 fsync,數據將徹底由內核控制寫入磁盤。對於 Linux 系統來講,每 30 秒寫入一次。

使用是推薦採用默認的 everysec 每秒同步策略,兼顧安全與效率。

寫時複製(copy-on-write):AOF 持久化的運行原理

  1. Redis 主進程執行 fork() 建立出子進程。
  2. 子進程開始將新 AOF 文件的內容寫入到臨時文件。
  3. 對於全部新執行的寫入命令,父進程一邊將它們累積到一個內存緩存中,一邊將這些改動追加到現有 AOF 文件的末尾: 這樣即便在重寫的中途發生停機,現有的 AOF 文件也仍是安全的。
  4. 當子進程完成重寫工做時,它給父進程發送一個信號,父進程在接收到信號以後,將內存緩存中的全部數據追加到新 AOF 文件的末尾。
  5. 搞定!如今 Redis 原子地用新文件替換舊文件,以後全部命令都會直接追加到新 AOF 文件的末尾。

摘自 Redis 持久化

優化 AOF 備份文件

咱們知道 AOF 的運行原理是不斷的將寫入的命令以 Redis 通訊協議的數據格式追加到 .aof 文件末尾,這就會致使文件的體積不斷增大。

若是全部的命令徹底不一樣到沒有關係。

可是,若是命令處理相似計數器的功能,好比執行 100 次 INCR(incr counter) 處理,AOF 文件會保存所有的 INCR 命令的執行記錄,但實際上咱們知道這些處理的結果同 set counter 100 並沒有二致。這就致使咱們的 .aof 多存儲了 99 條命令記錄。

這時,咱們就可使用 Redis 提供的 BGREWRITEAOF 重寫命令,將 AOF 文件進行重寫優化。

舉例:

SET name 'liugongzi'
SET age 18
SET name 'liugongzi handsome'

AOF 文件將這些寫入命令保存到(appendonly.aof)文件中,內容以下:

*2
$6
SELECT
$1
0
*3
$3
set
$4
name
$9
liugongzi
*3
$3
set
$3
age
$2
18
*3
$3
set
$4
name
$18
liugongzi handsome

寫入的內容徹底遵循 Redis 通訊協議。經過示例,咱們知道雖然咱們執行了兩次 set name 操做,但最終 Redis 保存的 name 值是 liugongzi handsome。也就是說第一次 set name 其實並沒有必要。

如今咱們經過 BGREWRITEAOF 命令對文件進行重寫處理:

127.0.0.1:6380> BGREWRITEAOF
Background append only file rewriting started

重寫完成後的 AOF 文件內容以下:

*2
$6
SELECT
$1
0
*3
$3
SET
$3
age
$2
18
*3
$3
SET
$4
name
$18
liugongzi handsome

經過對比重寫先後的文件內容,能夠發現 Redis 將第一次的 set name 'liugongzi' 操做給刪出掉了。這樣就達到優化 AOF 文件的目的。

補充一句 AOF 重寫,並非對 AOF 文件進行重寫,而是依據 Redis 在內存中當前的鍵值進行重寫的。

優勢

  • 提供比 RDB 持久化方案更安全的數據,因爲默認採用每秒進行持久化處理,全部即便服務器重啓或宕機,最多也就丟失 1 秒內的數據。
  • AOF 文件有序地保存了對數據庫執行的全部寫入操做, 這些寫入操做以 Redis 協議的格式保存, 所以 AOF 文件的內容很是容易被人讀懂, 對文件進行分析(parse)也很輕鬆

缺點

  • 相比於 RDB 持久化,AOF 文件會比 RDB 備份文件大得多。
  • AOF 持久化的速度可能比 RDB 持久化速度慢。
  • AOF 在過去曾經發生過這樣的 bug : 由於個別命令的緣由,致使 AOF 文件在從新載入時,沒法將數據集恢復成保存時的原樣。 (舉個例子,阻塞命令 BRPOPLPUSH 就曾經引發過這樣的 bug 。) 測試套件裏爲這種狀況添加了測試: 它們會自動生成隨機的、複雜的數據集, 並經過從新載入這些數據來確保一切正常。 雖然這種 bug 在 AOF 文件中並不常見, 可是對比來講, RDB 幾乎是不可能出現這種 bug 的。

摘自 Redis 持久化

Redis 數據恢復

經過前面的學習咱們瞭解到 Redis 是如何執行 RDB 和 AOF 持久化處理的,如今咱們簡單瞭解下 Redis 是如何恢復 RDB 或 AOF 備份中的數據。

咱們知道 Redis 是一種內存型的 NoSQL 數據庫(或者說數據結構),當服務重啓或宕機都會致使內存中的數據丟失。

因此,當 Redis 服務器重啓或恢復時,它會進行讀取 RDB 或 AOF 文件(若是存在的話)處理,將文件中的數據從新載入內存實現數據恢復操做。

Redis 數據恢復採用兩套恢復方案:

  • 開啓 AOF 持久化方案時,優先採用 AOF 文件進行數據恢復

這個很好理解,由於 AOF 持久化方案的數據保存是秒級的,因此相對於 RDB 持久化數據更完整,因此在啓動 Redis 服務器是,會在 AOF 啓用時有限載入 AOF 文件進行數據還原。

  • 未開啓 AOF 持久化方案是,Redis 經過載入 RDB 文件進行數據恢復

RDB 持久化配置

到這裏,相信你對 Redis 持久化已經有了至關大瞭解了,這節開始咱們將學習 Redis 配置文件,看看如何使用 RDB 和 AOF 持久化功能。

Redis 服務器配置文件默認是 redis.windows.conf

RDB 持久化配置選項

RDB 配置位於 SNAPSHOTTING 配置節點。

  • 開啓 / 關閉 RDB 持久化功能
  1. 嚴格來講 Redis 沒有提供相似 AOF 的 appendonly 指令來開啓 RDB 持久化功能,咱們能夠經過註釋掉 save 指令來關閉 RDB 備份方案。
#save 900 1
#save 300 10
#save 60 10000
  1. 或者使用 config set save "" 命令來關閉重寫,可是若是僅使用這條命令,僅在當前服務器運行時生效,因此重啓服務器依然從配置文件讀取 RDB 重寫規則。若是想永久生效,能夠運行 config rewrite 命令,將 config set save 命令結果寫入到配置文件。執行完 config rewrite 命令後會直接刪除 redis.windows.conf 配置中的 save 指令。
  • 是否啓用壓縮

經過 rdbcompression 指令完成,默認 yes 進行壓縮。

  • 修改備份文件名

使用 dbfilename 指令,默認值 dump.rdb

  • 修改備份文件存儲目錄

使用 dir 指令,默認值 your_redis_path。另外 AOF 備份數據一樣會保存到該目錄下。

AOF 持久化配置選項

AOF 配置位於 APPEND ONLY MODE 配置節點。

  • 開啓 / 關閉 AOF 持久化功能

開啓 AOF 持久化功能,經過 appendonly 指令完成,取值範圍 yes / no,默認:no 不開啓 AOF 重寫。

  • 修改備份文件名

appendfilename 指令完成,默認值 appendonly.aof

  • 設置持久化執行策略

請參考前文 appendfsync 指令說明。

  • AOF 備份文件重寫規則配置

以前咱們經過使用命令 BGREWRITEAOF 對 AOF 執行重寫,可是當咱們啓用 AOF 持久化功能後,Redis 默認會啓用 AOF 重寫優化,這個工做有兩條指令完成:

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

auto-aof-rewrite-percentage 指令表示,本次執行 AOF 重寫時,當 AOF 文件的大小是上次執行重寫時文件的百分之多少才能夠自動重寫。默認: 100 表示本次重寫時的 AOF 文件是上次 2 倍能夠自動重寫。

auto-aof-rewrite-min-size 這個指令用於設置進行 AOF 文件自動重寫的最小文件大小。

換言之,這兩條配置表示:當 AOF 文件大小達到 64mb 時,纔開始自動進行重寫。下一次只有當文件大小需達到 128 mb 才能再次重寫,以此類推。

  • 自動修復出錯的 AOF 數據

當咱們的 Redis 服務器宕機時,可能致使 AOF 文件的尾部數據不完整,在重啓 Redis 服務器可能致使數據不一致。此時能夠經過:

aof-load-truncated 指令在啓動 Redis 自動修復文件。它的取值範圍是 yes / no,默認爲 yes 重啓時自動修復。

一樣的咱們也能夠經過 redis-check-aof --fix 修復工具手動進行修復。

參考資料

手冊 - 持久化

Redis 設計與實現 - RDB

Redis 設計與實現 - AOF

[Redis 持久化解密]part 1 part 2 原文

How to disable Redis RDB?

Redis 詳解(七)------ AOF 持久化

NoSQL 之【Redis】學習(三):Redis 持久化 Snapshot 和 AOF 說明

Redis 配置文件 redis.conf 項目詳解

相關文章
相關標籤/搜索