本文主要介紹了 Redis 持久化的兩種機制:RDB 和 AOF,以及鍵過時的策略:惰性刪除和按期刪除,還有 RDB、AOF 和複製功能對過時鍵的處理。redis
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
爲了實現這一功能,服務器會維持一個記錄距離上次保存以後修改的次數的 dirty 計數器和一個記錄上次保存時間的 lastsave 屬性。ide
週期操做函數 serverCron 默認每一個 100 毫秒就會執行一次,它的其中一項工做就是檢查 save 選項設置的條件是否知足,若是知足的話就會執行 BGSAVE 命令。函數
RDB 文件有多個部分,包括握手字段 ‘REDIS’ 字符串,版本號,數據庫,’EOF’ 和校驗字段。性能
核心部分是數據庫字段,數據庫字段包括了握手字段 ‘SELECTDB’,數據庫編號和鍵值對,數據庫編號指示了這是第幾個數據庫,而鍵值對則保存了各項數據。大數據
鍵值對中除了類型和數據,還可能會有過時時間。對於不一樣類型的鍵值對,RDB 文件會用不一樣的方式來保存它們。
RDB 文件自己是一個通過壓縮的二進制文件,每次 SAVE 或者 BGSAVE 都會建立一個新的 RDB 文件,不支持追加操做。
AOF 是 Redis 持久化的第二種方式,在 AOF 和 RDB 同時開啓時,服務器會優先考慮從 AOF 恢復數據,由於 AOF 每次記錄間隔的時間更短。
和 RDB 直接記錄鍵值對不一樣,AOF 記錄的是命令。服務器在執行完一個寫命令之後,會把這條命令追加到服務器 aof_buf 緩衝區的末尾,並在一個適當的時候寫入文件。重建時服務器會建立一個僞客戶端,依次執行文件中的命令便可完成數據的載入。
AOF 的持久化發生在每次事件循環結束以前,會阻塞服務器。在持久化時會調用操做系統的 write 函數,但一般該函數會把數據保存在一個內存緩衝區裏面而不是馬上刷入磁盤。這就帶來一個安全問題。爲了不這個問題操做系統又提供了 fsync 和 fdatasync 兩個強制刷盤的同步函數。咱們把 write 稱爲寫入,把 fsync 和 fdatasync 稱爲同步。
服務器會在每次事件循環結束以前根據 appendfsync 選項寫入和同步 aof_buf 中的數據:
隨着服務器運行時間的流逝,AOF 文件中的內容會愈來愈多,文件的體積也會愈來愈大,不只會對宿主計算機形成影響,也拖慢了數據恢復所須要的時間。
AOF 重寫是指從新生成一個 AOF 文件替換原來的 AOF 文件。但這裏的重寫不會對原有的文件進行讀取、分析或者寫入,而是把數據庫中的鍵值對摺算成命令,從新寫入新的文件。
重寫是一個耗時的操做,所以 Redis 把它放到後臺去操做,對應的指令是 BGREWRITEAOF。在重寫過程當中服務器還可能接收新的指令,所以 Redis 會維護一個 AOF 重寫緩衝區,記錄重寫期間的寫命令,在重寫完成後追加到 AOF 文件末尾。
RDB 的優勢:
RDB 的缺點:
AOF 的優勢:
AOF 的缺點:
RDB 和 AOF 各有所長,RDB 體積小,恢復速度快,並且能夠生成快照;AOF 頻率更高,能夠保存更新的數據。通常來講,推薦同時使用。
Redis 採起的是惰性刪除和按期刪除配合使用的方式。
惰性刪除是指 Redis 會在訪問某個鍵的時候檢查該鍵是否過時,若是過時,就會將輸入鍵從數據庫中刪除。但惰性刪除不能及時清理內存,所以 Redis 還有按期刪除的機制。
按期刪除是另外一種過時鍵刪除方式。Redis 會維護一個過時字典(以下圖所示),全部聲明瞭過時時間的鍵都會被添加進這個字典中。週期操做函數 serverCron 執行時,會在規定時間內隨機檢查一部分鍵的過時時間,並刪除其中的過時鍵。
RDB 文件在生成時會檢查每一個鍵的過時時間,過時鍵不會被添加進 RDB 文件裏。
載入 RDB 文件時,若是該服務器是主服務器,則不會載入文件中過時的鍵;若是該服務器是從服務器,則不論過時與否都會被載入。不過,由於主從服務器在同步的時候,從服務器的數據庫會被清空,因此通常來說,過時鍵對載入 RDB 文件的從服務器不會形成影響。
AOF 文件寫入時,若是數據庫中的某個鍵已過時,但它還沒被刪除,那麼 AOF 文件不會由於這個鍵產生任何影響。當它被惰性刪除或者按期刪除以後,程序會向 AOF 文件追加一條 DEL 命令顯示記錄該鍵已被刪除。
AOF 重寫時,和生成 RDB 文件同樣,會過濾掉已通過期的鍵。
主服務器在刪除一個過時鍵後,會顯式地向全部從服務器發送一個 DEL 命令,告知從服務器刪除這個過時鍵。
Redis 3.2 前,爲了保持主從一致性,從服務器在執行客戶端發送的讀命令時,即便碰到過時鍵也不會將過時鍵刪除,而是繼續像處理未過時鍵同樣處理過時鍵。從服務器只有在接到主服務器發來的 DEL 命令以後,纔會刪除過時鍵。Redis 3.2 後,從節點在讀取數據時,增長了對數據是否過時的判斷:若是該數據已過時,則不返回給客戶端。