redis 是如何做持久化的

LastSun發表於2019-07-09

Redis 是一個鍵值對資料庫伺服器。基於記憶體儲存資料,它常被用做快取資料庫,用來替代 memcached。官網:https://redis.io/

什麼是持久化?

持久化,指將資料儲存到可永久儲存的裝置中。
例如,將記憶體中的資料儲存到可永久儲存的硬碟中。

為什麼需要持久化?

  1. Redis 基於記憶體儲存,記憶體掉電後資料會丟失
  2. 記憶體比硬碟貴得多,所以需要將一些不能丟失的資料持久化到硬碟上

甚至,一些特別重要的資料,是需要存到 MySQL 的。
Redis 本身有持久化,為什麼還要寫進 mysql 呢?:https://www.v2ex.com/t/219551

如何做持久化?

Redis 提供了四種持久化方式:

  1. RDB(Redis database|Snapshoting)
  2. AOF(Append-Only file)
  3. VM(虛擬記憶體)被淘汰了
  4. Diskstore 不瞭解

這次主要說的是 RDB 和 AOF 兩種持久化方式。

RDB 持久化

RDB:Redis database 的簡稱。一看這個,你就應該能猜到,這是 Redis 的預設持久化方式。

RDB 中持久化生成的是一個經過壓縮的二進位制檔案。

RDB 持久化時機:

  1. 在客戶端執行 SAVE 或者 BGSAVE
  2. 根據配置規則自動快照(稍後會講到)
  3. 執行 FLUSHALL 命令
  4. 執行復制(replication)

RDB 持久化步驟:

  1. fork 複製出一個父程式的副本子程式
  2. 子程式將記憶體中的資料寫入到硬碟中的臨時檔案
  3. 將臨時檔案替換舊的 rdb 檔案

圖片

自動間隔儲存(配置規則):

save 900 1     # 每900秒檢查一次,如果有1條資料修改了,那麼執行 rdb
save 300 10    # 每300秒檢查一次,如果有10條資料修改了,那麼執行 rdb
save 60 10000  # 每60秒檢查一次,如果有10000條資料修改了,那麼執行 rdb

RDB 檔案還原

伺服器啟動時,會直接載入 RDB 檔案。
但是如果 AOF 檔案存在,則會載入 AOF 檔案。AOF 檔案載入過程會在後文中描述

AOF 持久化

AOF 是 Append Only File 的簡稱。

AOF 通過儲存客戶端傳過來的寫命令來記錄資料庫的狀態。
如:

$3(後面是 \r\n)
SET
$3
msg
$1
5
$3
SET
$3
msg
$1
3

AOF 持久化的時機

需要在配置檔案中加入:

appendonly yes

AOF 持久化的步驟

主程式進行如文章末尾所示的三個步驟:

  1. 命令追加
  2. 檔案寫入
  3. 檔案同步

AOF 重寫的時機

  1. 配置:
# 當前 AOF 檔案超過上次重寫時的 AOF 檔案大小的百分之多少時再次進行重寫
# 如果之前沒有衝寫過,則以啟動時的 AOF 檔案大小為依據。
auto-aof-rewrite-percentage 100
# 允許重寫的最小值
auto-aof-rewrite-min-size 64mb
  1. 主動執行 BGREWRITEAOF 命令觸發 AOF 重寫。

AOF 重寫步驟

如果是在客戶端直接執行 REWRITEAOF ,會阻塞服務,直到重寫完成,將新的 AOF 檔案覆蓋舊的檔案。這種方式一般不會考慮。

BGREWRITEAOF 命令的執行過程如文末圖片所示:

  1. 父程式寫入 AOF 緩衝區和 AOF 重寫緩衝區
  2. 子程式執行 AOF 重寫,完成之後傳送訊號給父程式
  3. 父程式收到訊號將 AOF 重寫緩衝區的內容寫入到新的 AOF 檔案中,並且覆蓋原有的 AOF 檔案

AOF 重寫是將多條命令用一條命令代替。
如上面程式碼所示,儲存一個 msg 使用了兩條命令。經過 AOF 檔案重寫之後,就會變成如下所示,大大減少了使用的儲存空間:

$3
SET
$3
msg
$1

AOF 檔案還原

AOF 檔案還原的步驟如下:

  1. 建立一個偽客戶端(fake client)
  2. 從 AOF 檔案中分析並讀取一條寫命令
  3. 使用偽客戶端執行寫命令
  4. 一直重複步驟 2 和 3

AOF 寫入與重寫過程圖:

圖片

相關文章