Redis RDB檔案格式全解析

2021-07-05 17:39:08 字數 3876 閱讀 9051

rdb檔案是redis

持久化的一種方式,redis通過制定好的策略,按期將記憶體中的資料以映象的形式轉存到rdb檔案中。那麼rdb檔案內部格式是什麼樣的呢,redis又做了哪些工作讓rdb能夠更快的dump和載入呢,下面我們深入rdb檔案,來看一看其內部結構。

首先我們來看乙個rdb檔案的概況圖:

----------------------------# rdb檔案是二進位制的,所以並不存在回車換行來分隔一行一行.

52 45 44 49 53 # 以字串 "redis" 開頭

30 30 30 33 # rdb 的版本號,大端儲存,比如左邊這個表示版本號為0003

----------------------------

fe 00 # fe = fe表示資料庫編號,redis支援多個庫,以數字編號,這裡00表示第0個資料庫

----------------------------# key-value 對儲存開始了

fd $length-encoding # fd 表示過期時間,過期時間是用 length encoding 編碼儲存的,後面會講到

$value-type # 1 個位元組用於表示value的型別,比如set,hash,list,zset等

$string-encoded-key # key 值,通過string encoding 編碼,同樣後面會講到

$encoded-value # value值,根據不同的value型別採用不同的編碼方式

----------------------------

fc $length-encoding # fc 表示毫秒級的過期時間,後面的具體時間用length encoding編碼儲存

$value-type # 同上,也是乙個位元組的value型別

$string-encoded-key # 同樣是以 string encoding 編碼的 key值

$encoded-value # 同樣是以對應的資料型別編碼的 value 值

----------------------------

$value-type # 下面是沒有過期時間設定的 key-value對,為防止衝突,資料型別不會以 fd, fc, fe, ff 開頭

$string-encoded-key

$encoded-value

----------------------------

fe $length-encoding # 下乙個庫開始,庫的編號用 length encoding 編碼

----------------------------

... # 繼續儲存這個資料庫的 key-value 對

ff ## ff:rdb檔案結束的標誌

下面我們對上面的內容進行詳細講解

第一行就不用講了,redis字串用於標識是redis的rdb檔案

用了4個位元組儲存版本號,以大端(big endian)方式儲存和讀取

以乙個位元組的0xfe開頭,後面儲存資料庫的具體編號,資料庫的編號是乙個數字,通過 「length encoding」 方式編碼儲存,「length encoding」 我們後面會講到。

值對包括下面四個部分

key 過期時間,這一項是可有可無的

乙個位元組表示value的型別

key的值,key都是字串,通過 「redis string encoding」 來儲存

value的值,通過 「redis value encoding」 來根據不同的資料型別做不同的儲存

過期時間由 0xfd 或 0xfc開頭用於標識,分別表示秒級的過期時間和毫秒級的過期時間,後面的具體時間是乙個unix時間戳,秒級或毫秒級的。具體時間戳的值通過「redis length encoding」 編碼儲存。在匯入rdb檔案的過程中,會通過過期時間判斷是否已過期並需要忽略。

value型別用乙個位元組進行儲存,目前包括以下一些值:

key值就是簡單的 「string encoding」 編碼,具體可以看後面的描述

上面列舉了value的9種型別,實際上可以分為三大類

上面說了很多 length encoding ,現在就為大家講解。可能你會說,長度用乙個int儲存不就行了嗎?但是,通常我們使用到的長度可能都並不大,乙個int 4個位元組是否有點浪費呢。所以redis採用了變長編碼的方法,將不同大小的數字編碼成不同的長度。

首先在讀取長度時,會讀乙個位元組的資料,其中前兩位用於進行變長編碼的判斷

如果前兩位是 0 0,那麼下面剩下的 6位就表示具體長度

如果前兩位是 0 1,那麼會再讀取乙個位元組的資料,加上前面剩下的6位,共14位用於表示具體長度

如果前兩位是 1 0,那麼剩下的 6位就被廢棄了,取而代之的是再讀取後面的4 個位元組用於表示具體長度

如果前兩位是 1 1,那麼下面的應該是乙個特殊編碼,剩下的 6位用於標識特殊編碼的種類。特殊編碼主要用於將數字存成字串,或者編碼後的字串。具體見 「string encoding」

這樣做有什麼好處呢,實際就是節約空間:

0 – 63的數字只需要乙個位元組進行儲存

而64 – 16383 的數字只需要兩個位元組進行儲存

16383 - 2^32 -1 的數字只需要用5個位元組(1個位元組的標識加4個位元組的值)進行儲存

redis的 string encoding 是二進位制安全的,也就是說他沒有任何特殊分隔符用於分隔各個值,你可以在裡面儲存任何東西。它就是一串位元組碼。

下面是 string encoding 的三種型別

長度編碼的字串

數字替代字串:8位,16位或者32位的數字

lzf 壓縮的字串

長度編碼字串是最簡單的一種型別,它由兩部分組成,一部分是用 「length encoding」 編碼的字串長度,第二部分是具體的位元組碼。

上面說到過 length encoding 的特殊編碼,就在這裡用上了。所以數字替代字串是以 1 1 開頭的,然後讀取這個位元組剩下的6 位,根據不同的值標識不同的數字型別:

和資料替代字串一樣,它也是以1 1 開頭的,然後剩下的6 位如果值為4,那麼就表示它是乙個壓縮字串。壓縮字串解析規則如下:

首先按 length encoding 規則讀取壓縮長度 clen

然後按 length encoding 規則讀取非壓縮長度

再讀取第二個 clen

獲取到上面的三個資訊後,再通過lzf演算法解碼後面clen長度的位元組碼

redis list 結構在rdb檔案中的儲存,是依次儲存list中的各個元素的。其結構如下:

首先按 length encoding 讀取這個list 的長度 size

然後讀取 size個 string encoding的值

然後再用這些讀到的 size 個值重新構建 list就完成了

set結構和list結構一樣,也是依次儲存各個元素的

todo

首先按 length encoding 讀出hash 結構的大小 size

然後讀取2×size 個 string encoding的字串(因為乙個hash項包括key和value兩項)

將上面讀取到的2×size 個字串解析為hash 和key 和 value

然後將上面的key value對儲存到hash結構中

參見本站之前的文章:redis zipmap記憶體布局分析

ziplist encoding

intset encoding

sorted set as ziplist encoding

QuickTime檔案格式解析

peter lee 2008 06 14 一 簡介 quicktime 是公司開發的一套完整的多 平台架構,可以用來進行多種 的建立,生產,和分發,並為這一過程提供端到端的支援 包括 的實時捕捉,以程式設計的方式合成 匯入和匯出現有的 還有編輯和製作,壓縮,分發,以及使用者回放等多個環節。quick...

sol檔案格式解析

在網上搜了一遍只看到這個分析 sharedobject sol檔案頭總是00 bf,接著4個位元組是大小 這個大小是之後所有塊的大小哦 然後也是固定的54 43 53 4f 00 04 00 00 00 00。第17 18位元組是sharedobject變數名的長度,緊跟著就是sharedobjec...

FLV檔案格式解析

flv是流 封裝格式,我們可以將其資料看為二進位制位元組流。總體上看,flv包括檔案頭 file header 和檔案體 file body 兩部分,其中檔案體由一系列的tag及tag size對組成。因此乙個flv檔案看上去是下面的結構 其中,previous tag size 緊跟在每個 tag...