1. 程式人生 > 其它 >Redis設計與實現 第 10 章 RDB 持久化

Redis設計與實現 第 10 章 RDB 持久化

第 10 章 RDB 持久化

資料庫狀態:伺服器中的非空資料庫以及它們的鍵值對統稱為資料庫狀態

Redis 提供 RDB 持久化功能,將記憶體中的資料庫狀態儲存到磁碟中,避免資料意外丟失

RDB 檔案是一個經過壓縮的二進位制檔案,還可以通過該檔案還原生成 RDB 檔案時的資料庫狀態

10.1 RDB 檔案的建立與載入

SAVE、BGSAVE命令生成 RDB 檔案

SAVE 命令會阻塞 Redis 伺服器程序,直到檔案建立完畢,阻塞期間無法處理任何請求

BGSAVE 命令會派生子程序,由子程序負責建立 RDB 檔案,伺服器父程序繼續處理命令請求

建立 RDB 檔案的實際工作由 rdb.c/rdbSave 完成,兩個命令會以不同的方式呼叫此函式

RDB 檔案的載入工作在伺服器啟動時自動執行的,只要檢測到 RDB 檔案存在,自動載入 RDB 檔案

AOF檔案更新頻率通常比 RDB 檔案的更新頻率高,所以:

  • 如果伺服器開啟了 AOF 持久化功能,伺服器會優先使用 AOF 檔案來還原資料庫狀態
  • 只有在 AOF 持久化功能關閉才會使用 RDB 檔案來還原狀態

10.1.1 SAVE 命令執行時的伺服器狀態

阻塞,只有命令執行完成後客戶端的命令才會被處理

10.1.2 BGSAVE 命令執行時的伺服器狀態

伺服器可以繼續處理命令請求,但有些區別

  • SAVE 命令被拒絕
  • BGSAVE 命令也被拒絕
  • BGREWRITEAOF 不能同時執行
    • BGSAVE 在執行,被延遲到前者完成後
    • 正在執行,BGSAVE 被拒絕
    • 效能方面考慮,兩個子程序同時執行大量寫入操作

10.1.3 RDB 檔案載入時伺服器的狀態

阻塞

10.2 自動間隔性儲存

設定伺服器配置 save 選項,讓伺服器妹隔一段時間自動執行一次BGSAVE 選項

save 900 1
save 300 10
save 60 10000

在 900 s 內,對資料庫進行了至少一次修改

同理

三個條件滿足一個,BGSAVE 命令就會執行

10.2.1 設定儲存條件

save 900 1
save 300 10
save 60 10000

以上為預設設定,如果沒有指定配置引數或者傳入啟動引數方式

伺服器會根據 save 選項設定 redisServer.saveparams 屬性

預設情況如下:

10.2.2 dirty 計數器和 lastsave 屬性

  • dirty計數器
    • 記錄距離上一次執行 SAVE 命令或者 BGSAVE 命令之後伺服器對資料庫進行了多少次修改
  • lastsave
    • UNIX 時間戳
      • 記錄了伺服器上一次成功執行 SAVE 命令或 BGSAVE 命令的時間

伺服器成功執行一次資料庫修改命令之後就對 dirty 計數器進行更新

10.2.3 檢查儲存條件是否滿足

serverCron 預設每隔 100 ms 執行一次,對執行的伺服器維護,其中一項工作就是檢查設定的儲存條件是否滿足,是則執行 BGSAVE 命令

10.3 RDB 檔案結構

完整的 RDB 檔案結構如下:

常量:全大寫單詞

變數和資料:全小寫單詞

  • REDIS:5 位元組,儲存 “REDIS” 5 個字元,方便程式快速分辨為 RDB 檔案

RDB 為二進位制資料,“REDIS” 儲存的不是 c 字串

  • db_version:4 位元組,為字串表示的常數, REB 版本號

  • database

    • 零個或多個數據庫,以及資料庫中的鍵值對資料

    • 如果資料庫狀態為空,此處也為空,長度 0 位元組

    • 資料庫狀態非空,根據情況不同,長度不同

  • EOF:常量,1 位元組,標誌 RDB 檔案正文內容結束,即所有資料庫所有鍵值對載入完成

  • check_num:8 位元組無符號整數,校驗和,通過前四個部分計算而來,載入時計算是否與之相同驗證檔案是否損壞

10.3.1 database 部分

database 可以儲存任意多個非空資料庫

假設 0 號、3 號資料庫非空, RDB 檔案如圖,database 代表 0 號資料庫中的所有鍵值對

database 0 又可以再細分

  • SELECTDB:1 位元組,表明接下來讀入的是資料庫號碼

  • db_number:資料庫號碼,可以為1 3 5 位元組

  • key_value_pairs:資料庫中的所有鍵值對資料,如果有過期時間也會儲存在一起

10.3.2 key_value_pairs 部分

不帶過期時間的鍵值對

TYPE KEY VALUE
  • TYPE:1 位元組
  • value:字串物件,同上襦的 String 型別

帶過期時間的鍵值對

EXPIRETIME_MS MS TYPE KEY VALUE
  • EXPIRETIME_MS:1 位元組,告知程式即將讀入的是毫秒為單位的過期時間
  • ms:8 位元組的帶符號整數,毫秒為單位為 UNIX 時間戳

10.3.3 value 編碼

1.字串物件:REDIS_RDB_TYPE_STRING

value 儲存的為字串物件,編碼有 REDIS_ENCODING_INT 或者 REDIS_ENCODING_RAW

  • REDIS_ENCODING_INT

    • 長度不超過 32 位的整數

    • ENCODING 可以是 REDIS_RDB_ENC_INT8、REDIS_RDB_ENC_INT16、REDIS_RDB_ENC_INT32 代表使用幾位來儲存整數值 integer

  • REDIS_ENCODING_RAW

    • 字串物件

    • 壓縮與不壓縮儲存

      • 小於等於 20 位元組,原樣儲存

      • 大於 20 位元組,壓縮之後再儲存

      • 在伺服器開啟 RDB 檔案壓縮功能進行的

      • 否則總是無壓縮儲存

    • 無壓縮

    • 壓縮

      • REDIS_RDB_ENC_LZF:常量,表示字串被 LZF 演算法壓縮了,程式會對後面三個欄位使用解壓縮
      • compressed_len:壓縮之後的長度
      • origin_len:壓縮之前的長度
      • compressed_string:壓縮之後的字串

2.列表物件:REDIS_RDB_TYPE_LIST

value 儲存的是 REDIS_ENCODING_LINKEDLIST 編碼的列表物件

  • list_length:列表長度,列表儲存了多少個項

  • item:列表的列表項,每個列表項都是字串物件

    • 包含長度與實際值

3.集合物件:REDIS_RDB_TYPE_SET

REDIS_ENCODING_HT

  • set_size:集合大小

  • elem:字串物件

    • 包含長度與實際值

4.雜湊表物件:REDIS_RDB_TYPE_HASH

REDIS_ENCODING_HT

鍵與值相鄰排列

5.有序集合物件:REDIS_RDB_TYPE_ZSET

REDIS_ENCODING_SKIPLIST

成員與分值緊挨,分值為 double 浮點數,在 double、字串中互相轉換

6.INTSET 編碼集合:REDIS_RDB_TYPE_INTSET

整數集合與字串互相轉換

7.ZIPLIST 編碼的列表、雜湊表或者有序集合

REDIS_RDB_TYPE_LIST_ZIPLIST

REDIS_RDB_TYPE_HASH_ZIPLIST

REDIS_RDB_TYPE_ZSET_ZIPLIST

壓縮列表

  1. 壓縮列表轉換字串

  2. 字串儲存到 RDB

  3. 字串轉換壓縮列表

  4. 根據 TYPE 設定型別

    • REDIS_RDB_TYPE_LIST_ZIPLIST:列表
    • REDIS_RDB_TYPE_HASH_ZIPLIST:雜湊表
    • REDIS_RDB_TYPE_ZSET_ZIPLIST:有序集合