Redis 源码简洁剖析 13 - RDB 文件

RDB 是什么

Redis *.rdb 是内存的二进制文件,通过 *.rdb 能够完全回复 Redis 的运行状态。

![](
20220218175013.png?x-oss-process=style/yano)

RDB 文件格式

详细信息可参考:Redis RDB Dump File Format。

Redis 源码简洁剖析 13 - RDB 文件

Redis 源码简洁剖析 13 - RDB 文件

Header

RDB 文件的头部占用 9bytes,前 5bytes 为 Magic String, 后 4bytes 为版本号;

52 45 44 49 53 #"REDIS", 就像 java 的 class 文件以 0xCAFEBABE 开头一样 30 30 30 36 #RDB 版本号,30 表示‘0’,版本号为 0006=6

注意:版本号是字符串而不是整型:

snprintf(magic,sizeof(magic),"REDIS%04d",RDB_VERSION);

RDB_VERSION 详细信息可参考:Redis RDB Version History

Body DB Selector

FE 开头表示后跟表示 DB Selector,例如:

FE 00 #FE 表明数据库的哪个 db,此处为 db0

注意:DB Selector 长度不固定,具体的编码方式请参见后文的 Length 编码。

AUX Fields

FA 开头表示后跟 AUX Fields, 记录生成 Dump 文件的 Redis 相关信息,例如 redis-ver、redis-bits、used-mem、aof-preamble 和 repl-id 等。这些信息采用 String 编码;

注意:redis3.0 版本的 RDB 版本号为 6,redis3.2 的版本号为 7;

Key-Value

key-value 有三种格式:

expire 为 second

FD $unsigned int #失效时间(秒),4 个字节 $value-type #1 个字节,表明数据类型:set,map 等 $string-encoded-key #key 值,字符串类型 $encoded-value #value, 编码方式和类型有关

expire 为 millisecond

FC $unsigned long #失效时间(毫秒),8 个字节 $value-type #数据类型,1 个字节 $string-encoded-key #key,字符串类型 $encoded-value #value, 编码方式和类型有关

无 expire

$value-type #数据类型,1 个字节 $string-encoded-key #key,字符串类型 $encoded-value #value, 编码方式和类型有关

Footer FF #RDB 文件的结束 8byte checksum #循环冗余校验码,Redis 采用 crc-64-jones 算法,初始值为 0 编码算法说明 Length 编码

长度采用 BigEndian 格式存储,为无符号整数

如果以"00"开头,那么接下来的 6 个 bit 表示长度;

如果以“01”开头,那么接下来的 14 个 bit 表示长度;

如果以"10"开头,该 byte 的剩余 6bit 废弃,接着读入 4 个 bytes 表示长度 (BigEndian);

如果以"11"开头,那么接下来的 6 个 bit 表示特殊的编码格式,一般用来存储数字:

0 表示用接下来的 1byte 表示长度

1 表示用接下来的 2bytes 表示长度;

2 表示用接下来的 4bytes 表示长度;

String 编码

该编码方式首先采用 Length 编码 进行解析:

从上面的Length 编码知道,如果以"00","01","10"开头,首先读取长度;然后从接下来的内容中读取指定长度的字符;

如果以"11"开头,而且接下来的 6 个字节为“0”、“1”和“2”, 那么直接读取接下来的 1,2,4bytes 做为字符串的内容(实际上存储的是数字,只不过按照字符串的格式存储);

如果以“11”开头,而且接下来的 6 个字节为"3", 表明采用 LZF 压缩字符串格式:

LZF 编码的解析步骤为:

首先采用Length 编码读取压缩后字符串的长度 clen;

接着采用Length 编码读取压缩前的字符串长度;

读取 clen 长度的字节,并采用 lzf 算法解压得到原始的字符串

Score 编码

读取 1 个字节,如果为 255,则返回负无穷;

如果为 254,返回正无穷;

如果为 253,返回非数字;

否则,将该字节的值做为长度,读取该长度的字节,将结果做为分值;

Value 编码

Redis 中的 value 编码包括如下类型:

其中 String 编码在前面已经介绍过,接下来逐一介绍其他的 9 种编码方式;

List

首先用 Length 编码读取 List 的长度 lsize;

采用 String 编码读取 lsize 个字符串

Set

同 List

Sorted Set

首先用 Length 编码读取 Sorted Set 的长度 zsize;

采用 String 编码读取字符串,采用 Score 编码读取分值;

循环读取 zsize 次;

Hash

采用 Length 编码读取 Hash 的大小 hsize;

采用 String 编码读取 2*hsize 的字符串,按照 key,value 的方式组装成 Map

Zipmap

用于存储 hashmap,Redis2.6 之后,该编码被废弃,转而采用 Ziplist 编码;

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgwgdj.html