Redis 持久化和過時機制

本文主要介紹了 Redis 持久化的兩種機制:RDB 和 AOF,以及鍵過時的策略:惰性刪除和按期刪除,還有 RDB、AOF 和複製功能對過時鍵的處理。redis

RDB

RDB 是 Redis 持久化的第一種方式。有兩個 Redis 命令能夠用於生成 RDB 文件,一個是 SAVE,另外一個是 BGSAVE。
SAVE 會阻塞 Redis 服務器進程,執行時 Redis 服務器會阻塞全部客戶端發送的命令。數據庫

redis> SAVE
OK

BGSAVE 會派生出一個子進程執行,執行時仍可繼續處理客戶端的命令,但會拒絕客戶端 SAVE 和 BGSAVE 的命令,延遲 BGREWRITEAOF 命令。安全

redis> BGSAVE
Background saving started

執行條件

SAVE 命令會阻塞服務器,因此只能手動執行。BGSAVE 能夠在不阻塞的狀況下執行,因此能夠配置 save 選項讓服務器每隔一段時間自動執行一次。服務器

好比咱們能夠向服務器提供如下配置:app

save  900  1
save  300  10
save  60  10000

那麼只要知足如下三個條件中的任意一個便可被執行:async

  • 服務器在 900 秒以內對數據庫進行了至少 1 次修改。
  • 服務器在 300 秒以內對數據庫進行了至少 10 次修改。
  • 服務器在 60 秒以內對數據庫進行了至少 10000 次修改。

爲了實現這一功能,服務器會維持一個記錄距離上次保存以後修改的次數的 dirty 計數器和一個記錄上次保存時間的 lastsave 屬性。ide

週期操做函數 serverCron 默認每一個 100 毫秒就會執行一次,它的其中一項工做就是檢查 save 選項設置的條件是否知足,若是知足的話就會執行 BGSAVE 命令。函數

文件內容

RDB 文件有多個部分,包括握手字段 ‘REDIS’ 字符串,版本號,數據庫,’EOF’ 和校驗字段。性能

核心部分是數據庫字段,數據庫字段包括了握手字段 ‘SELECTDB’,數據庫編號和鍵值對,數據庫編號指示了這是第幾個數據庫,而鍵值對則保存了各項數據。大數據

鍵值對中除了類型和數據,還可能會有過時時間。對於不一樣類型的鍵值對,RDB 文件會用不一樣的方式來保存它們。

RDB 文件自己是一個通過壓縮的二進制文件,每次 SAVE 或者 BGSAVE 都會建立一個新的 RDB 文件,不支持追加操做。

AOF

AOF 是 Redis 持久化的第二種方式,在 AOF 和 RDB 同時開啓時,服務器會優先考慮從 AOF 恢復數據,由於 AOF 每次記錄間隔的時間更短。

和 RDB 直接記錄鍵值對不一樣,AOF 記錄的是命令。服務器在執行完一個寫命令之後,會把這條命令追加到服務器 aof_buf 緩衝區的末尾,並在一個適當的時候寫入文件。重建時服務器會建立一個僞客戶端,依次執行文件中的命令便可完成數據的載入。

文件的寫入與同步

AOF 的持久化發生在每次事件循環結束以前,會阻塞服務器。在持久化時會調用操做系統的 write 函數,但一般該函數會把數據保存在一個內存緩衝區裏面而不是馬上刷入磁盤。這就帶來一個安全問題。爲了不這個問題操做系統又提供了 fsync 和 fdatasync 兩個強制刷盤的同步函數。咱們把 write 稱爲寫入,把 fsync 和 fdatasync 稱爲同步。

服務器會在每次事件循環結束以前根據 appendfsync 選項寫入和同步 aof_buf 中的數據:

  • always:寫入並同步
  • everysec:寫入,若是距離上次同步超過 1 秒,則同步
  • no:只寫入,什麼時候同步由操做系統決定

AOF 重寫

隨着服務器運行時間的流逝,AOF 文件中的內容會愈來愈多,文件的體積也會愈來愈大,不只會對宿主計算機形成影響,也拖慢了數據恢復所須要的時間。

AOF 重寫是指從新生成一個 AOF 文件替換原來的 AOF 文件。但這裏的重寫不會對原有的文件進行讀取、分析或者寫入,而是把數據庫中的鍵值對摺算成命令,從新寫入新的文件。

重寫是一個耗時的操做,所以 Redis 把它放到後臺去操做,對應的指令是 BGREWRITEAOF。在重寫過程當中服務器還可能接收新的指令,所以 Redis 會維護一個 AOF 重寫緩衝區,記錄重寫期間的寫命令,在重寫完成後追加到 AOF 文件末尾。

RDB 和 AOF 對比

RDB 的優勢

  • RDB 是一個很是緊湊的文件,它的體積更小,且能夠選擇持久化的時間,適合作備份的文件。好比天天的備份,每個月的備份。
  • RDB 對主進程更友好,父進程只須要 fork 出一個子進程,無須執行任何磁盤 I/O 操做。
  • RDB 在恢復大數據集時的速度比 AOF 的恢復速度要快。

RDB 的缺點

  • 由於 RDB 文件須要保存整個數據集的狀態, 因此它並非一個輕鬆的操做。 所以你可能會至少 5 分鐘才保存一次 RDB 文件,間隔時間比較長。
  • RDB 雖然會把持久化的操做交給子進程,但每次都會從頭開始,在數據集比較龐大時, fork() 可能會很是耗時,形成服務器在某某毫秒內中止處理客戶端; 若是數據集很是巨大,而且 CPU 時間很是緊張的話,那麼這種中止時間甚至可能會長達整整一秒。

AOF 的優勢

  • AOF 使用追加的方式,每次寫入時間很短,所以能夠容許更短間隔的持久化操做,好比 1 秒。
  • AOF 文件的可讀性比較好,若是你不當心執行了一條命令,只要 AOF 文件未被重寫,那麼只要中止服務器,移除 AOF 文件裏的該條命令而後重啓 Redis 便可。

AOF 的缺點

  • 對於相同的數據集來講,AOF 文件的體積一般要大於 RDB 文件的體積。
  • 使用 fsync 會下降 Redis 的性能,致使 AOF 的速度可能會慢於 RDB 。

RDB 和 AOF 各有所長,RDB 體積小,恢復速度快,並且能夠生成快照;AOF 頻率更高,能夠保存更新的數據。通常來講,推薦同時使用。

Redis 過時機制

Redis 採起的是惰性刪除和按期刪除配合使用的方式。

惰性刪除是指 Redis 會在訪問某個鍵的時候檢查該鍵是否過時,若是過時,就會將輸入鍵從數據庫中刪除。但惰性刪除不能及時清理內存,所以 Redis 還有按期刪除的機制。

按期刪除是另外一種過時鍵刪除方式。Redis 會維護一個過時字典(以下圖所示),全部聲明瞭過時時間的鍵都會被添加進這個字典中。週期操做函數 serverCron 執行時,會在規定時間內隨機檢查一部分鍵的過時時間,並刪除其中的過時鍵。

Redis 持久化和過時機制

RDB、AOF 和複製功能對過時鍵的處理

RDB 對過時鍵的處理

RDB 文件在生成時會檢查每一個鍵的過時時間,過時鍵不會被添加進 RDB 文件裏。

載入 RDB 文件時,若是該服務器是主服務器,則不會載入文件中過時的鍵;若是該服務器是從服務器,則不論過時與否都會被載入。不過,由於主從服務器在同步的時候,從服務器的數據庫會被清空,因此通常來說,過時鍵對載入 RDB 文件的從服務器不會形成影響。

AOF 對過時鍵的處理

AOF 文件寫入時,若是數據庫中的某個鍵已過時,但它還沒被刪除,那麼 AOF 文件不會由於這個鍵產生任何影響。當它被惰性刪除或者按期刪除以後,程序會向 AOF 文件追加一條 DEL 命令顯示記錄該鍵已被刪除。

AOF 重寫時,和生成 RDB 文件同樣,會過濾掉已通過期的鍵。

複製功能對過時鍵的處理

主服務器在刪除一個過時鍵後,會顯式地向全部從服務器發送一個 DEL 命令,告知從服務器刪除這個過時鍵。

Redis 3.2 前,爲了保持主從一致性,從服務器在執行客戶端發送的讀命令時,即便碰到過時鍵也不會將過時鍵刪除,而是繼續像處理未過時鍵同樣處理過時鍵。從服務器只有在接到主服務器發來的 DEL 命令以後,纔會刪除過時鍵。Redis 3.2 後,從節點在讀取數據時,增長了對數據是否過時的判斷:若是該數據已過時,則不返回給客戶端。

相關文章
相關標籤/搜索