Redis RDB文件格式全解析
RDB文件是Redis持久化的一種方式,Redis通過(guò)制定好的策略,按期將內(nèi)存中的數(shù)據(jù)以鏡像的形式轉(zhuǎn)存到RDB文件中。那么RDB文件內(nèi)部格式是什么樣的呢,Redis又做了哪些工作讓RDB能夠更快的dump和加載呢,下面我們深入RDB文件,來(lái)看一看其內(nèi)部結(jié)構(gòu)。
首先我們來(lái)看一個(gè)RDB文件的概況圖:
----------------------------# RDB文件是二進(jìn)制的,所以并不存在回車換行來(lái)分隔一行一行. 52 45 44 49 53 # 以字符串 "REDIS" 開頭 30 30 30 33 # RDB 的版本號(hào),大端存儲(chǔ),比如左邊這個(gè)表示版本號(hào)為0003 ---------------------------- FE 00 # FE = FE表示數(shù)據(jù)庫(kù)編號(hào),Redis支持多個(gè)庫(kù),以數(shù)字編號(hào),這里00表示第0個(gè)數(shù)據(jù)庫(kù) ----------------------------# Key-Value 對(duì)存儲(chǔ)開始了 FD $length-encoding # FD 表示過(guò)期時(shí)間,過(guò)期時(shí)間是用 length encoding 編碼存儲(chǔ)的,后面會(huì)講到 $value-type # 1 個(gè)字節(jié)用于表示value的類型,比如set,hash,list,zset等 $string-encoded-key # Key 值,通過(guò)string encoding 編碼,同樣后面會(huì)講到 $encoded-value # Value值,根據(jù)不同的Value類型采用不同的編碼方式 ---------------------------- FC $length-encoding # FC 表示毫秒級(jí)的過(guò)期時(shí)間,后面的具體時(shí)間用length encoding編碼存儲(chǔ) $value-type # 同上,也是一個(gè)字節(jié)的value類型 $string-encoded-key # 同樣是以 string encoding 編碼的 Key值 $encoded-value # 同樣是以對(duì)應(yīng)的數(shù)據(jù)類型編碼的 Value 值 ---------------------------- $value-type # 下面是沒有過(guò)期時(shí)間設(shè)置的 Key-Value對(duì),為防止沖突,數(shù)據(jù)類型不會(huì)以 FD, FC, FE, FF 開頭 $string-encoded-key $encoded-value ---------------------------- FE $length-encoding # 下一個(gè)庫(kù)開始,庫(kù)的編號(hào)用 length encoding 編碼 ---------------------------- ... # 繼續(xù)存儲(chǔ)這個(gè)數(shù)據(jù)庫(kù)的 Key-Value 對(duì) FF ## FF:RDB文件結(jié)束的標(biāo)志下面我們對(duì)上面的內(nèi)容進(jìn)行詳細(xì)講解
Magic Number
第一行就不用講了,REDIS字符串用于標(biāo)識(shí)是Redis的RDB文件
版本號(hào)
用了4個(gè)字節(jié)存儲(chǔ)版本號(hào),以大端(big endian)方式存儲(chǔ)和讀取
數(shù)據(jù)庫(kù)編號(hào)
以一個(gè)字節(jié)的0xFE開頭,后面存儲(chǔ)數(shù)據(jù)庫(kù)的具體編號(hào),數(shù)據(jù)庫(kù)的編號(hào)是一個(gè)數(shù)字,通過(guò) “Length Encoding” 方式編碼存儲(chǔ),“Length Encoding” 我們后面會(huì)講到。
Key-Value值對(duì)
值對(duì)包括下面四個(gè)部分
Key過(guò)期時(shí)間
過(guò)期時(shí)間由?0xFD 或 0xFC開頭用于標(biāo)識(shí),分別表示秒級(jí)的過(guò)期時(shí)間和毫秒級(jí)的過(guò)期時(shí)間,后面的具體時(shí)間是一個(gè)UNIX時(shí)間戳,秒級(jí)或毫秒級(jí)的。具體時(shí)間戳的值通過(guò)“Redis Length Encoding” 編碼存儲(chǔ)。在導(dǎo)入RDB文件的過(guò)程中,會(huì)通過(guò)過(guò)期時(shí)間判斷是否已過(guò)期并需要忽略。
Value類型
Value類型用一個(gè)字節(jié)進(jìn)行存儲(chǔ),目前包括以下一些值:
- 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值就是簡(jiǎn)單的 “String Encoding” 編碼,具體可以看后面的描述
Value
上面列舉了Value的9種類型,實(shí)際上可以分為三大類
- type = 0, 簡(jiǎn)單字符串
- type 為 ?9, 10, 11 或 12, value字符串在讀取出來(lái)后需要先解壓
- type 為 1, 2, 3 或 4, value是字符串序列,這一系列的字符串用于構(gòu)建list,set,hash 和 zset 結(jié)構(gòu)
Length Encoding
上面說(shuō)了很多 Length Encoding ,現(xiàn)在就為大家講解。可能你會(huì)說(shuō),長(zhǎng)度用一個(gè)int存儲(chǔ)不就行了嗎?但是,通常我們使用到的長(zhǎng)度可能都并不大,一個(gè)int 4個(gè)字節(jié)是否有點(diǎn)浪費(fèi)呢。所以Redis采用了變長(zhǎng)編碼的方法,將不同大小的數(shù)字編碼成不同的長(zhǎng)度。
這樣做有什么好處呢,實(shí)際就是節(jié)約空間:
String Encoding
Redis的 String Encoding 是二進(jìn)制安全的,也就是說(shuō)他沒有任何特殊分隔符用于分隔各個(gè)值,你可以在里面存儲(chǔ)任何東西。它就是一串字節(jié)碼。
下面是 String Encoding 的三種類型
長(zhǎng)度編碼字符串
長(zhǎng)度編碼字符串是最簡(jiǎn)單的一種類型,它由兩部分組成,一部分是用 “Length Encoding” 編碼的字符串長(zhǎng)度,第二部分是具體的字節(jié)碼。
數(shù)字替代字符串
上面說(shuō)到過(guò) Length Encoding 的特殊編碼,就在這里用上了。所以數(shù)字替代字符串是以 1 1 開頭的,然后讀取這個(gè)字節(jié)剩下的6 位,根據(jù)不同的值標(biāo)識(shí)不同的數(shù)字類型:
- 0 表示下面是一個(gè)8 位的數(shù)字
- 1 表示下面是一個(gè)16 位的數(shù)字
- 2 表示下面是一個(gè)32 位的數(shù)字
LZF壓縮字符串
和數(shù)據(jù)替代字符串一樣,它也是以1 1 開頭的,然后剩下的6 位如果值為4,那么就表示它是一個(gè)壓縮字符串。壓縮字符串解析規(guī)則如下:
List Encoding
Redis List 結(jié)構(gòu)在RDB文件中的存儲(chǔ),是依次存儲(chǔ)List中的各個(gè)元素的。其結(jié)構(gòu)如下:
Set Encoding
Set結(jié)構(gòu)和List結(jié)構(gòu)一樣,也是依次存儲(chǔ)各個(gè)元素的
Sorted Set Encoding
todo
Hash Encoding
Zipmap Encoding
參見本站之前的文章:Redis zipmap內(nèi)存布局分析
待續(xù)&歡迎投稿
Ziplist Encoding
Intset Encoding
Sorted Set as Ziplist Encoding
來(lái)源:RDB_File_Format.textile
from:?http://blog.nosqlfan.com/html/3734.html
總結(jié)
以上是生活随笔為你收集整理的Redis RDB文件格式全解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深入剖析Redis RDB持久化机制
- 下一篇: Redis集群教程