Redis持久化 - RDB和AOF

1、持久化的做用

1. 什麼是持久化

持久化(Persistence),即把數據(如內存中的對象)保存到可永久保存的存儲設備中(如磁盤)。
持久化Redis全部數據保持在內存中,對數據的更新將異步地保存到磁盤上。redis

Redis持久化

2. 持久化的實現方式

快照方式持久化

快照方式持久化就是在某時刻把全部數據進行完整備份。sql

例:Mysql的Dump方式、Redis的RDB方式。數據庫

寫日誌方式持久化

寫日誌方式持久化就是把用戶執行的全部寫指令(增刪改)備份到文件中,還原數據時只須要把備份的全部指令從新執行一遍便可。安全

例:Mysql的Binlog、Redis的AOF、Hbase的HLog。服務器

2、RDB

1. 什麼是RDB

RDB簡介

RDB持久化

RDB持久化方式可以在指定的時間間隔能對你的數據進行快照存儲。
在默認狀況下, Redis 將數據庫快照保存在名字爲 dump.rdb的二進制文件中。
在 Redis 運行時, RDB 程序將當前內存中的數據庫快照保存到磁盤文件中, 在 Redis 重啓動時, RDB 程序能夠經過載入 RDB 文件來還原數據庫的狀態。app

工做方式

當 Redis 須要保存 dump.rdb 文件時, 服務器執行如下操做:異步

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

這種工做方式使得 Redis 能夠從寫時複製(copy-on-write)機制中獲益。工具

2. RDB的三種主要觸發機制

save命令(同步數據到磁盤上)

save 命令執行一個同步操做,以RDB文件的方式保存全部數據的快照。性能

127.0.0.1:6379> save
OK

save命令

因爲 save 命令是同步命令,會佔用Redis的主進程。若Redis數據很是多時,save命令執行速度會很是慢,阻塞全部客戶端的請求。
所以不多在生產環境直接使用SAVE 命令,可使用BGSAVE 命令代替。若是在BGSAVE命令的保存數據的子進程發生錯誤的時,用 SAVE命令保存最新的數據是最後的手段。優化

save命令阻塞全部客戶端的請求

bgsave命令(異步保存數據到磁盤上)

bgsave 命令執行一個異步操做,以RDB文件的方式保存全部數據的快照。

127.0.0.1:6379> bgsave
Background saving started

Redis使用Linux系統的fock()生成一個子進程來將DB數據保存到磁盤,主進程繼續提供服務以供客戶端調用。
若是操做成功,能夠經過客戶端命令LASTSAVE來檢查操做結果。

bgsave命令

savebgsave 對比

命令 save bgsave
IO類型 同步 異步
阻塞? 是(阻塞發生在fock(),一般很是快)
複雜度 O(n) O(n)
優勢 不會消耗額外的內存 不阻塞客戶端命令
缺點 阻塞客戶端命令 須要fock子進程,消耗內存

自動生成RDB

除了手動執行 savebgsave 命令實現RDB持久化之外,Redis還提供了自動自動生成RDB的方式。

你能夠經過配置文件對 Redis 進行設置, 讓它在「 N 秒內數據集至少有 M 個改動」這一條件被知足時, 自動進行數據集保存操做。
好比說, 如下設置會讓 Redis 在知足「 60 秒內有至少有 1000 個鍵被改動」這一條件時, 自動進行數據集保存操做:

save 60 1000

自動生成RDB

3. RDB相關配置

# RDB自動持久化規則
# 當 900 秒內有至少有 1 個鍵被改動時,自動進行數據集保存操做
save 900 1
# 當 300 秒內有至少有 10 個鍵被改動時,自動進行數據集保存操做
save 300 10
# 當 60 秒內有至少有 10000 個鍵被改動時,自動進行數據集保存操做
save 60 10000

# RDB持久化文件名
dbfilename dump-<port>.rdb

# 數據持久化文件存儲目錄
dir /var/lib/redis

# bgsave發生錯誤時是否中止寫入,一般爲yes
stop-writes-on-bgsave-error yes

# rdb文件是否使用壓縮格式
rdbcompression yes

# 是否對rdb文件進行校驗和檢驗,一般爲yes
rdbchecksum yes

4. RDB的優勢

  1. RDB是一個很是緊湊的文件,它保存了某個時間點得數據集,很是適用於數據集的備份,好比你能夠在每一個小時報保存一下過去24小時內的數據,同時天天保存過去30天的數據,這樣即便出了問題你也能夠根據需求恢復到不一樣版本的數據集。
  2. RDB是一個緊湊的單一文件,很方便傳送到另外一個遠端數據中心或者亞馬遜的S3(可能加密),很是適用於災難恢復。
  3. RDB在保存RDB文件時父進程惟一須要作的就是fork出一個子進程,接下來的工做所有由子進程來作,父進程不須要再作其餘IO操做,因此RDB持久化方式能夠最大化redis的性能。
  4. 與AOF相比,在恢復大的數據集的時候,RDB方式會更快一些。

5. RDB的缺點

  1. 耗時、耗性能。RDB 須要常常fork子進程來保存數據集到硬盤上,當數據集比較大的時候,fork的過程是很是耗時的,可能會致使Redis在一些毫秒級內不能響應客戶端的請求。若是數據集巨大而且CPU性能不是很好的狀況下,這種狀況會持續1秒,AOF也須要fork,可是你能夠調節重寫日誌文件的頻率來提升數據集的耐久度。
  2. 不可控、丟失數據。若是你但願在redis意外中止工做(例如電源中斷)的狀況下丟失的數據最少的話,那麼RDB不適合你。雖然你能夠配置不一樣的save時間點(例如每隔5分鐘而且對數據集有100個寫的操做),是Redis要完整的保存整個數據集是一個比較繁重的工做,你一般會每隔5分鐘或者更久作一次完整的保存,萬一在Redis意外宕機,你可能會丟失幾分鐘的數據。

3、AOF

1. 什麼是AOF

快照功能(RDB)並非很是耐久(durable): 若是 Redis 由於某些緣由而形成故障停機, 那麼服務器將丟失最近寫入、且仍未保存到快照中的那些數據。 從 1.1 版本開始, Redis 增長了一種徹底耐久的持久化方式: AOF 持久化。
你能夠在配置文件中打開AOF方式:

appendonly yes

打開AOF後, 每當 Redis 執行一個改變數據集的命令時(好比 SET), 這個命令就會被追加到 AOF 文件的末尾。這樣的話, 當 Redis 從新啓時, 程序就能夠經過從新執行 AOF 文件中的命令來達到重建數據集的目的。

AOF運行原理 - 建立

建立AOF

AOF運行原理 - 恢復

AOF運行原理 - 恢復

2. AOF持久化的三種策略

你能夠經過配置文件配置 Redis 多久纔將數據 fsync 到磁盤一次。

always

每次有新命令追加到 AOF 文件時就執行一次 fsync :很是慢,也很是安全。

always

everysec

每秒 fsync 一次:足夠快(和使用 RDB 持久化差很少),而且在故障時只會丟失 1 秒鐘的數據。
推薦(而且也是默認)的措施爲每秒 fsync 一次, 這種 fsync 策略能夠兼顧速度和安全性。

everysec

no

從不 fsync :將數據交給操做系統來處理,由操做系統來決定何時同步數據。更快,也更不安全的選擇。

no

always、everysec、no對比

命令 優勢 缺點
always 不丟失數據 IO開銷大,通常SATA磁盤只有幾百TPS
everysec 每秒進行與fsync,最多丟失1秒數據 可能丟失1秒數據
no 不用管 不可控

推薦(而且也是默認)的措施爲每秒 fsync 一次, 這種 fsync 策略能夠兼顧速度和安全性。

3. AOF重寫

由於 AOF 的運做方式是不斷地將命令追加到文件的末尾, 因此隨着寫入命令的不斷增長, AOF 文件的體積也會變得愈來愈大。舉個例子, 若是你對一個計數器調用了 100 次 INCR , 那麼僅僅是爲了保存這個計數器的當前值, AOF 文件就須要使用 100 條記錄(entry)。然而在實際上, 只使用一條 SET 命令已經足以保存計數器的當前值了, 其他 99 條記錄實際上都是多餘的。
爲了處理這種狀況, Redis 支持一種有趣的特性: 能夠在不打斷服務客戶端的狀況下, 對 AOF 文件進行重建(rebuild)。執行 bgrewriteaof 命令, Redis 將生成一個新的 AOF 文件, 這個文件包含重建當前數據集所需的最少命令。
Redis 2.2 須要本身手動執行 bgrewriteaof 命令; Redis 2.4 則能夠經過配置自動觸發 AOF 重寫。

AOF重寫

AOF重寫的做用

  • 減小磁盤佔用量
  • 加速數據恢復

AOF重寫的實現方式

  • bgrewriteaof 命令

    Redis bgrewriteaof 命令用於異步執行一個 AOF(AppendOnly File)文件重寫操做。重寫會建立一個當前AOF文件的體積優化版本。
    即便 bgrewriteaof 執行失敗,也不會有任何數據丟失,由於舊的AOF文件在 bgrewriteaof 成功以前不會被修改。
    AOF 重寫由 Redis 自行觸發,bgrewriteaof 僅僅用於手動觸發重寫操做。
    具體內容:

    • 若是一個子Redis是經過磁盤快照建立的,AOF重寫將會在RDB終止後纔開始保存。這種狀況下BGREWRITEAOF任然會返回OK狀態碼。從Redis 2.6起你能夠經過INFO命令查看AOF重寫執行狀況。
    • 若是隻在執行的AOF重寫返回一個錯誤,AOF重寫將會在稍後一點的時間從新調用。

bgrewriteaof命令

  • AOF重寫配置
配置名 含義
auto-aof-rewrite-min-size 觸發AOF文件執行重寫的最小尺寸
auto-aof-rewrite-percentage 觸發AOF文件執行重寫的增加率
統計名 含義
aof_current_size AOF文件當前尺寸(字節)
aof_base_size AOF文件上次啓動和重寫時的尺寸(字節)

AOF重寫自動觸發機制,須要同時知足下面兩個條件:

  • aof_current_size > auto-aof-rewrite-min-size
  • (aof_current_size - aof_base_size) * 100 / aof_base_size > auto-aof-rewrite-percentage

假設 Redis 的配置項爲:

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

當AOF文件的體積大於64Mb,而且AOF文件的體積比上一次重寫之久的體積大了至少一倍(100%)時,Redis將執行 bgrewriteaof 命令進行重寫。

AOF重寫的流程

AOF重寫的流程*

3. AOF相關配置

# 開啓AOF持久化方式
appendonly yes

# AOF持久化文件名
appendfilename appendonly-<port>.aof

# 每秒把緩衝區的數據同步到磁盤
appendfsync everysec

# 數據持久化文件存儲目錄
dir /var/lib/redis

# 是否在執行重寫時不一樣步數據到AOF文件
# 這裏的 yes,就是執行重寫時不一樣步數據到AOF文件
no-appendfsync-on-rewrite yes

# 觸發AOF文件執行重寫的最小尺寸
auto-aof-rewrite-min-size 64mb

# 觸發AOF文件執行重寫的增加率
auto-aof-rewrite-percentage 100

4. AOF的優勢

  1. 使用AOF 會讓你的Redis更加耐久: 你可使用不一樣的fsync策略:無fsync,每秒fsync,每次寫的時候fsync。使用默認的每秒fsync策略,Redis的性能依然很好(fsync是由後臺線程進行處理的,主線程會盡力處理客戶端請求),一旦出現故障,你最多丟失1秒的數據。
  2. AOF文件是一個只進行追加的日誌文件,因此不須要寫入seek,即便因爲某些緣由(磁盤空間已滿,寫的過程當中宕機等等)未執行完整的寫入命令,你也也可以使用redis-check-aof工具修復這些問題。
  3. Redis 能夠在 AOF 文件體積變得過大時,自動地在後臺對 AOF 進行重寫: 重寫後的新 AOF 文件包含了恢復當前數據集所需的最小命令集合。 整個重寫操做是絕對安全的,由於 Redis 在建立新 AOF 文件的過程當中,會繼續將命令追加到現有的 AOF 文件裏面,即便重寫過程當中發生停機,現有的 AOF 文件也不會丟失。 而一旦新 AOF 文件建立完畢,Redis 就會從舊 AOF 文件切換到新 AOF 文件,並開始對新 AOF 文件進行追加操做。
  4. AOF 文件有序地保存了對數據庫執行的全部寫入操做, 這些寫入操做以 Redis 協議的格式保存, 所以 AOF 文件的內容很是容易被人讀懂, 對文件進行分析(parse)也很輕鬆。 導出(export) AOF 文件也很是簡單: 舉個例子, 若是你不當心執行了 FLUSHALL 命令, 但只要 AOF 文件未被重寫, 那麼只要中止服務器, 移除 AOF 文件末尾的 FLUSHALL 命令, 並重啓 Redis , 就能夠將數據集恢復到 FLUSHALL 執行以前的狀態。

5. AOF的缺點

  1. 對於相同的數據集來講,AOF 文件的體積一般要大於 RDB 文件的體積。
  2. 根據所使用的 fsync 策略,AOF 的速度可能會慢於 RDB 。 在通常狀況下, 每秒 fsync 的性能依然很是高, 而關閉 fsync 可讓 AOF 的速度和 RDB 同樣快, 即便在高負荷之下也是如此。 不過在處理巨大的寫入載入時,RDB 能夠提供更有保證的最大延遲時間(latency)。

4、RDB和AOF的抉擇

1. RDB 和 AOF 對比

- RDB AOF
啓動優先級
體積
恢復速度
數據安全性 丟數據 根據策略決定

2. 如何選擇使用哪一種持久化方式?

通常來講, 若是想達到足以媲美 PostgreSQL 的數據安全性, 你應該同時使用兩種持久化功能。

若是你很是關心你的數據, 但仍然能夠承受數分鐘之內的數據丟失, 那麼你能夠只使用 RDB 持久化。

有不少用戶都只使用 AOF 持久化, 但並不推薦這種方式: 由於定時生成 RDB 快照(snapshot)很是便於進行數據庫備份, 而且 RDB 恢復數據集的速度也要比 AOF 恢復的速度要快。

相關文章
相關標籤/搜索