Redis 持久化

Redis 有兩種持久化的方式: 快照 (RDB文件) 和追加式文件 (AOF文件):redis

  • RDB 持久化方式會在一個特定的間隔保存那個時間點的一個數據快照.
  • AOF 持久化方式則會記錄每個服務器收到的寫操做. 在服務啓動時, 這些記錄的操做會逐條執行從而重建出原來的數據. 寫操做命令記錄的格式跟 Redis 協議一致, 以追加的方式進行保存.
  • Redis 的持久化是能夠禁用的, 就是說你可讓數據的生命週期只存在於服務器的運行時間裏.
  • 兩種方式的持久化是能夠同時存在的, 可是當 Redis 重啓時, AOF文件會被優先用於重建數據.

RDB

工做原理

  • Redis 調用 fork(), 產生一個子進程.
  • 子進程把數據寫到一個臨時的 RDB 文件.
  • 當子進程寫完新的 RDB 文件後, 把舊的 RDB 文件替換掉.

文件路徑和名稱

默認 Redis 會把快照文件存儲爲當前目錄下一個名爲 dump.rdb 的文件. 要修改文件的存儲路徑和名稱, 能夠經過修改配置文件 redis.conf 實現:安全

# RDB文件名,默認爲dump.rdb。
dbfilename dump.rdb

# 文件存放的目錄,AOF文件一樣存放在此目錄下。默認爲當前工做目錄。
dir ./

保存點 (RDB的啓用和禁用)

你能夠配置保存點, 使 Redis 若是在每 N 秒後數據發生了 M 次改變就保存快照文件. 例以下面這個保存點配置表示每 60 秒, 若是數據發生了 1000 次以上的變更, Redis就會自動保存快照文件:服務器

save 60 1000

保存點能夠設置多個, Redis 的配置文件就默認設置了 3 個保存點:app

# 格式爲:save <seconds> <changes>
# 能夠設置多個。
save 900 1 #900秒後至少1個key有變更
save 300 10 #300秒後至少10個key有變更
save 60 10000 #60秒後至少10000個key有變更

若是想禁用快照保存的功能, 能夠經過註釋掉全部 "save" 配置達到,或者在最後一條 "save" 配置後添加以下的配置:性能

save ""

錯誤處理

默認狀況下, 若是 Redis 在後臺生成快照的時候失敗, 那麼就會中止接收數據, 目的是讓用戶能知道數據沒有持久化成功.spa

可是若是你有其餘的方式能夠監控到 Redis 及其持久化的狀態, 那麼能夠把這個功能禁止掉.3d

stop-writes-on-bgsave-error yes

數據壓縮

默認 Redis 會採用 LZF 對數據進行壓縮.code

若是你想節省點 CPU 的性能, 你能夠把壓縮功能禁用掉, 可是數據集就會比沒壓縮的時候要大.blog

rdbcompression yes

數據校驗

從版本 5 的 RDB 的開始, 一個 CRC64 的校驗碼會放在文件的末尾. 這樣更能保證文件的完整性, 可是在保存或者加載文件時會損失必定的性能 (大概10%).生命週期

若是想追求更高的性能, 能夠把它禁用掉, 這樣文件在寫入校驗碼時會用 0 替代, 加載的時候看到 0 就會直接跳過校驗.

rdbchecksum yes

手動生成快照

Redis 提供了兩個命令用於手動生成快照.

BGSAVE

BGSAVE 命令使用後臺的方式保存 RDB 文件, 調用此命令後, 會馬上返回OK.

Redis 會產生一個子進程進行快照寫入硬盤. 父進程繼續處理命令請求.

SAVE

SAVE 命令會使用同步的方式生成 RDB 快照文件, 這意味着在這個過程當中會阻塞全部其餘客戶端的請求.

所以不建議在生產環境使用這個命令.

重點

  1. 若是用戶設置了 save 60 1000, 那麼從 Redis 最近一次建立快照以後開始算起. 當條件被知足時, 就會自動出發 BGSAVE 命令. 若是有多個 save 配置, 那麼當任意一個被知足時, 都會出發一次 BGSAVE 命令.
  2. 當 Redis 經過 SHUTDOWN 命令, 來關閉服務時, 或者接收到標準 TERM 信號時, 會執行一次 SAVE 命令, 阻塞全部客戶端, 而且執行完畢後會關閉 Redis 服務.

clipboard.png

這裏注意的是 fork 操做會阻塞, 致使 Redis 讀寫性能降低. 咱們能夠控制單個 Redis 實例的最大內存, 來儘量下降 Redis 在 fork 時的事件消耗. 以及上面提到的自動觸發的頻率減小 fork 次數, 或者使用手動觸發, 根據本身的機制來完成持久化.

AOF

快照並非很可靠. 若是你的電腦忽然宕機了, 或者電源斷了, 又或者不當心殺掉了進程, 那麼最新的數據就會丟失.

而 AOF 文件則提供了一種更爲可靠的持久化方式. 每當 Redis 接受到會修改數據集的命令時, 就會把命令追加到 AOF 文件裏, 當你重啓 Redis 時, AOF 裏的命令會被從新執行一次, 重建數據.

啓用 AOF

把配置項 appendonly 設爲 yes:

appendonly yes

文件路徑和名稱

# 文件存放目錄,與RDB共用。默認爲當前工做目錄。
dir ./

# 默認文件名爲appendonly.aof
appendfilename "appendonly.aof"

可靠性

你能夠配置 Redis 調用 fsync 的頻率, 有三個選項:

  • 每當有新命令追加到 AOF 的時候調用 fsync. 速度最慢, 最安全.
  • 每秒 fsync 一次. 速度快 (2.4版本跟快照方式速度差很少), 安全性不錯 (最多丟失 1 秒的數據).
  • 從不 fsync, 交由系統去處理. 這個方式速度最快, 可是安全性通常.

推薦使用每秒 fsync 一次的方式 (默認的方式), 由於它速度快, 安全性也不錯. 相關配置以下:

# appendfsync always
appendfsync everysec
# appendfsync no

對於增量追加到文件這一步主要的流程是: 命令寫入=》追加到 aof_buf =》同步到aof磁盤. 那麼這裏爲何要先寫入 buf 在同步到磁盤呢? 若是實時寫入磁盤會帶來很是高的磁盤IO, 影響總體性能.

AOF 重寫是爲了減小 AOF 文件的大小, 隨着寫操做的不斷增長, AOF 文件會愈來愈大. 例如你遞增一個計數器 100 次, 那麼最終結果就是數據集裏的計數器的值爲最終的遞增結果, 可是 AOF 文件裏卻會把這 100 次操做完整的記錄下來.

而事實上要恢復這個記錄, 只須要 1 個命令就好了, 也就是說 AOF 文件裏那 100 條命令其實能夠精簡爲 1 條. 因此 Redis 支持這樣一個功能: 在不中斷服務的狀況下在後臺重建 AOF 文件.

clipboard.png

對於上圖有四個關鍵點補充一下:

  • 在重寫期間, 因爲主進程依然在響應命令, 爲了保證最終備份的完整性; 所以它依然會寫入舊的 AOF file 中, 若是重寫失敗, 可以保證數據不丟失.
  • 爲了把重寫期間響應的寫入信息也寫入到新的文件中, 所以也會爲子進程保留一個 buf, 防止新寫的 file 丟失數據.
  • 重寫是直接把當前內存的數據生成對應命令, 並不須要讀取老的 AOF 文件進行分析、命令合併.
  • AOF 文件直接採用的文本協議, 主要是兼容性好、追加方便、可讀性高可認爲修改修復.

性能與實踐

經過上面的分析, 咱們都知道 RDB 的快照、AOF的重寫都須要 fork, 這是一個重量級操做, 會對 Redis 形成阻塞. 所以爲了避免影響 Redis 主進程響應, 咱們須要儘量下降阻塞.

  • 下降 fork 的頻率, 好比能夠手動來觸發 RDB 生成快照、與AOF重寫;
  • 控制 Redis 最大使用內存, 防止 fork 耗時過長;
  • 使用更牛逼的硬件;
  • 合理配置 Linux 的內存分配策略, 避免由於物理內存不足致使 fork 失敗.

在線上咱們到底該怎麼作? 我提供一些本身的實踐經驗.

  • 若是 Redis 中的數據並非特別敏感或者能夠經過其它方式重寫生成數據, 能夠關閉持久化;
  • 本身制定策略按期檢查 Redis 的狀況, 而後能夠手動觸發備份、重寫數據;
  • 單機若是部署多個實例, 要防止多個機器同時運行持久化、重寫操做, 防止出現內存、CPU、IO資源競爭, 讓持久化變爲串行;
  • 能夠加入主從機器, 利用一臺從機器進行備份處理, 其它機器正常響應客戶端的命令;
  • RDB 持久化與 AOF 持久化能夠同時存在, 配合使用.
相關文章
相關標籤/搜索