Redis RDB文件格式全解析

日期: 2012-03-13 作者:nosqlfan 来源:TechTarget中国

  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结构中

  Zipmap Encoding

  参见之前的文章:Redis zipmap内存布局分析

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

电子邮件地址不会被公开。 必填项已用*标注

敬请读者发表评论,本站保留删除与本文无关和不雅评论的权力。

作者

nosqlfan
nosqlfan

相关推荐