Redis RDB文件格式全解析

轉載自  Redis RDB文件格式全解析

點評

這篇文章作爲對RDB理解的教程文章,對RDB文件的原理理解有助於進行Redis高階應用的設計與開發。

文章轉自:http://blog.nosqlfan.com/html/3734.html 作者:@nosqlfan

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文件結束的標誌

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

Magic Number

第一行就不用講了,REDIS字符串用於標識是Redis的RDB文件

版本號

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

數據庫編號

以一個字節的0xFE開頭,後面存儲數據庫的具體編號,數據庫的編號是一個數字,通過 “Length Encoding” 方式編碼存儲,“Length Encoding” 我們後面會講到。

Key-Value值對

值對包括下面四個部分 1. Key 過期時間,這一項是可有可無的 2. 一個字節表示value的類型 3. Key的值,Key都是字符串,通過 “Redis String Encoding” 來保存 4. Value的值,通過 “Redis Value Encoding” 來根據不同的數據類型做不同的存儲

Key過期時間

過期時間由 0xFD 或 0xFC開頭用於標識,分別表示秒級的過期時間和毫秒級的過期時間,後面的具體時間是一個UNIX時間戳,秒級或毫秒級的。具體時間戳的值通過“Redis Length Encoding” 編碼存儲。在導入RDB文件的過程中,會通過過期時間判斷是否已過期並需要忽略。

Value類型

Value類型用一個字節進行存儲,目前包括以下一些值:

  • 0 = “String Encoding”

  • 1 = “List Encoding”

  • 2 = “Set Encoding”

  • 3 = “Sorted Set Encoding”

  • 4 = “Hash Encoding”

  • 9 = “Zipmap Encoding”

  • 10 = “Ziplist Encoding”

  • 11 = “Intset Encoding”

  • 12 = “Sorted Set in Ziplist Encoding”

Key

Key值就是簡單的 “String Encoding” 編碼,具體可以看後面的描述

Value

上面列舉了Value的9種類型,實際上可以分爲三大類

  • type = 0, 簡單字符串

  • type 爲 9, 10, 11 或 12, value字符串在讀取出來後需要先解壓

  • type 爲 1, 2, 3 或 4, value是字符串序列,這一系列的字符串用於構建list,set,hash 和 zset 結構

Length Encoding

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

  1. 首先在讀取長度時,會讀一個字節的數據,其中前兩位用於進行變長編碼的判斷

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

  3. 如果前兩位是 0 1,那麼會再讀取一個字節的數據,加上前面剩下的6位,共14位用於表示具體長度

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

  5. 如果前兩位是 1 1,那麼下面的應該是一個特殊編碼,剩下的 6位用於標識特殊編碼的種類。特殊編碼主要用於將數字存成字符串,或者編碼後的字符串。具體見 “String Encoding”

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

  1. 0 – 63的數字只需要一個字節進行存儲

  2. 而64 – 16383 的數字只需要兩個字節進行存儲

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

String Encoding

Redis的 String Encoding 是二進制安全的,也就是說他沒有任何特殊分隔符用於分隔各個值,你可以在裏面存儲任何東西。它就是一串字節碼。下面是 String Encoding 的三種類型

  1. 長度編碼的字符串

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

  3. LZF 壓縮的字符串

長度編碼字符串

長度編碼字符串是最簡單的一種類型,它由兩部分組成,一部分是用 “Length Encoding” 編碼的字符串長度,第二部分是具體的字節碼。

數字替代字符串

上面說到過 Length Encoding 的特殊編碼,就在這裏用上了。所以數字替代字符串是以 1 1 開頭的,然後讀取這個字節剩下的6 位,根據不同的值標識不同的數字類型:

  • 0 表示下面是一個8 位的數字

  • 1 表示下面是一個16 位的數字

  • 2 表示下面是一個32 位的數字

LZF壓縮字符串

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

  1. 首先按 Length Encoding 規則讀取壓縮長度 clen

  2. 然後按 Length Encoding 規則讀取非壓縮長度

  3. 再讀取第二個 clen

  4. 獲取到上面的三個信息後,再通過LZF算法解碼後面clen長度的字節碼

List Encoding

Redis List 結構在RDB文件中的存儲,是依次存儲List中的各個元素的。其結構如下:

  1. 首先按 Length Encoding 讀取這個List 的長度 size

  2. 然後讀取 size個 String Encoding的值

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

Set Encoding

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

Sorted Set Encoding

todo

Hash Encoding

  1. 首先按 Length Encoding 讀出hash 結構的大小 size

  2. 然後讀取2×size 個 String Encoding的字符串(因爲一個hash項包括key和value兩項)

  3. 將上面讀取到的2×size 個字符串解析爲hash 和key 和 value

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章