欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

RDB 文件结构

程序员文章站 2022-05-28 12:09:11
...
        在RDB 持久化一节中,我们对 RDB 持久化功能进行了详细的介绍,这一节将对 RDB 文件结构作进一步的剖析。
        一个完成的 RDB 文件结构按顺序包含如下几个部分:
        * REDIS 常量:RDB 文件的最开头部分,长度为 5 个字节,保存着“REDIS”五个字符(没有普通 C 字符串末尾的'\0'字符,因为 RDB 文件保存的是二进制数据),程序在载入文件时可凭此快速检查所载入的文件是否是 RDB 文件。
        * db_version:长度为 4 个字节的字符串表示的整数,记录了 RDB 文件的版本号,比如“0006”就代表 RDB 文件的版本为第六版。
        * databases:这部分包含零个或任意多个数据库,以及各个数据库中的键值对数据,其实际长度随数据库所保存键值对的数量、类型和内容的不同而有所不同。
        * EOF 常量:RDB 文件正文内容结束标记,长度为 1 字节。
        * check_sum:8 字节长的无符号整数,保存着程序对前面几个部分内容计算得出的校验和,用于在载入 RDB 文件时,通过与新计算的载入数据校验和做比对,以此来检查 RDB 文件是否有出错或者损坏的情况出现。
        接下来重点说一下 databases 部分。
        一个 RDB 文件的 databases 部分是由所有非空数据库所组成,每个非空数据库按顺序包含三个部分:
        * SELECTDB 常量:长度为 1 字节,标识接下来将要读入一个新的数据库。
        * db_number:表示几号数据库。根据号码的大小不同,其长度可以是 1 字节、2字节或者 5 字节。当程序读入这部分后,就会立即调用 SELECT 命令切换到对应的数据库,使得之后读入的键值对可以载入到正确的数据库中。
        * key_value_pairs:这部分保存了对应号码数据库中的所有键值对数据,过期时间(如果有)也会随之保存。这部分的长度与键值对的数量、类型、内容以及是否有过期时间等条件有关。
        下图是一个完整的 RDB 文件结构示意图,其中包含了 0 号数据块库和 3 号数据库。
RDB 文件结构
            
    
    博客分类: redis redis持久化rdbaof 
        这里的 pairs 部分保存了一个以上的键值对,以及可能的过期时间。一个带有过期时间的键值对在 RDB 文件中的结构包含以下几个部分(无过期时间的键值对没有前面两个字段):
        * EXPIRETIME_MS 常量:长度为 1 字节,标识着即将读入一个以毫秒为单位的过期时间。
        * ms:8 字节长的有符号整数,记录着一个以毫秒为单位的 UNIX 时间戳,表示的就是对应键的过期时间。
        * TYPE 常量:长度为 1 字节,记录了键值的类型,值可以是以下常量之一:REDIS_RDB_TYPE_STRING、REDIS_RDB_TYPE_LIST、REDIS_RDB_TYPE_SET、REDIS_RDB_TYPE_ZSET、REDIS_RDB_TYPE_HASH、REDIS_RDB_TYPE_LIST_ZIPLIST、REDIS_RDB_TYPE_SET_INTSET、REDIS_RDB_TYPE_ZSET_ZIPLIST、REDIS_RDB_TYPE_HASH_ZIPLIST。这里的每个 TYPE 常量都代表了一种对象类型或者底层编码,程序会根据这个值来决定如何读入和解释后续的 value 数据。
        * key:键值对的键对象,总是一个编码同 REDIS_RDB_TYPE_STRING 类型的 value 一样的字符串对象。其长度跟内容长度有关。
        * value:键值对的值对象。根据 TYPE 类型以及保存内容长度的不同,保存 value 的结构和长度也会有所不同。
        下面来说一下每个键值对的 value 值对象在 RDB 文件中的保存结构情况。
        如果 TYPE 的值为 REDIS_RDB_TYPE_STRING,说明 value 保存的就是一个字符串对象,字符串对象的编码可以是 REDIS_ENCODING_INT 或者 REDIS_ENCODING_RAW。
        若字符串对象的编码为 REDIS_ENCODING_INT,表示对象中保存的是长度不超过 32 位的整数,这种编码的对象将以“ENCODING + integer”的结构保存,其中的 ENCODING 常量可以是 REDIS_RDB_ENC_INT8、REDIS_RDB_ENC_INT16 或者 REDIS_RDB_ENC_INT32,分别代表整数值 integer 是 8 位、16 位或者 32 位。
        若字符串对象的编码为 REDIS_ENCODING_RAW,表示对象所保存的是一个字符串值。根据字符串长度的不同,有压缩和不压缩两种方法来保存这个字符串(当然,这要在服务器打开了 RDB 文件压缩功能的情况下,如果服务器关闭了 RDB 文件压缩功能,则总是以无压缩的方式保存字符串值,具体可参考 rdbcompression 配置选项说明):如果字符串的长度大于 20 字节,则该字符串会被压缩之后再保存,否则直接原样保存。
        对于没有被压缩的字符串,RDB 会以“len + string”的结构来保存,如下图表示保存的是一个无压缩的长度为 5 的“hello”字符串。
RDB 文件结构
            
    
    博客分类: redis redis持久化rdbaof 
        而对于压缩后的字符串,其保存结构则如下图所示。
RDB 文件结构
            
    
    博客分类: redis redis持久化rdbaof 
        其中,REDIS_RDB_ENC_LZF 常量表示字符串已被 LZF 算法压缩过了,之后的 compressed_len 记录的是字符串被压缩后的长度,origin_len 记录的则是原始长度,compressed_string 是压缩后的字符串。下图是一个压缩后的字符串示例,从中可以看出,字符串原本的长度为 21,压缩后的长度为 6,压缩后的内容为“?aa???”,这里的“?”代表无法用字符串形式打印出来的字节。
RDB 文件结构
            
    
    博客分类: redis redis持久化rdbaof 
        其他 TYPE 类型的对象的保存方式都是采取同样的形式,即“elementNum + elements”,只是对于其中的数值内容,程序会先将其转换成字符串对象后,再用保存字符串对象的方法进行保存。
        以有序集合为例,即 TYPE 的值为 REDIS_RDB_TYPE_ZSET,此时 value 保存的就是一个 REDIS_ENCODING_SKIPLIST 编码的有序集合对象,每个 element 由“member + score”两部分构成,其中 member 是一个字符串对象,score 则是一个 double 类型的浮点数,程序在保存 RDB 文件时就会将 score 部分转换成字符串对象后再保存。下图就是一个拥有两个元素的有序集合的保存示例。
RDB 文件结构
            
    
    博客分类: redis redis持久化rdbaof 
        其中,第一个数字 2 表示有序集合的元素数量,之后跟着的两个有序集合元素:第一个元素是长度为 2 的字符串“pi”,其分值 score 部分被转换成字符串后变成了长度为 4 的字符串“3.14”;第二个元素是长度为 1 的字符串“e”,其分值 score 部分被转换成字符串后变成了长度为 3 的字符串“2.7”。


参考书籍:《Redis 设计与实现》第十章——RDB 持久化。
  • RDB 文件结构
            
    
    博客分类: redis redis持久化rdbaof 
  • 大小: 16.2 KB
  • RDB 文件结构
            
    
    博客分类: redis redis持久化rdbaof 
  • 大小: 3.1 KB
  • RDB 文件结构
            
    
    博客分类: redis redis持久化rdbaof 
  • 大小: 14.3 KB
  • RDB 文件结构
            
    
    博客分类: redis redis持久化rdbaof 
  • 大小: 7.4 KB
  • RDB 文件结构
            
    
    博客分类: redis redis持久化rdbaof 
  • 大小: 7.4 KB