Redis(9)----RDB文件结构

1,前言

有关RDB文件生成相关的可以看:RDB持久化
本文涉及到的各种对象:Redis对象与数据结构

2,RDB文件结构

一个完整的RDB文件的示意图如下:

在这里插入图片描述

【为了方便区分变量、数据、常量,全文中用全大写单词标示常量,用全小写单词标示变量和数据】

  • RDB文件开头是REDIS部分,这个部分长5个字节,保存着REDIS五个字符。通过这五个字符,程序可以在载入文件时,快速判断是否是RDB文件
  • db_version长度为4个字节,它的值是一个字符串表示的整数,记录了RDB文件的版本号,比如0006表示RDB文件的版本为第六版
  • databases部分包含着零个或者任意个数据库,以及数据库中的键值对数据
  • EOF常量的长度为一个字节,这个常量标示着RDB文件正文内容的结束
  • check_sum是一个8字节长的无符号整数,保存着一个校验和,这个校验和是程序通过对REDIS、db_version、databases、EOF四个部分的内容进行计算得出的。服务器在载入时,会将载入数据计算得出的校验和与check_sum进行比较,以此判断是否出现出错或者损坏

示例:

在这里插入图片描述

2.1,databases部分

一个RDB文件的databases部分可以保存任意多个非空数据库,假设有一个服务器,其0号与3号数据库非空,那么其RDB文件为:
在这里插入图片描述

而每个非空数据库在RDB中又是按以下结构进行保存的:

在这里插入图片描述

  • SELECTDB常量的长度是一个字节,当读入程序遇到这个值的时候,它知道接下来要读入的将是一个数据库号码
  • db_number保存着一个数据库号码,根据号码的大小不同,这个部分的长度可以是1字节、2字节或者5字节。当读入db_number后,服务器会调用SELECT命令,根据读入的数据库号进行数据库切换,使得之后读入的键值对可以载入到正确的数据库中
  • key_value_pairs部分保存了数据库中的所有键值对数据,如果键值对带有过期时间,那么过期时间也会和键值对保存在一起

在这里插入图片描述

2.2,key_value_pairs部分

RDB文件中的每个key_value_pairs部分都保存了一个或以上数量的键值对,如果键值对带有过期时间的话,那么键值对的过期时间也会被保存在内

如果不带有过期时间的话,结构会是这样的:

在这里插入图片描述

带有过期时间的话,结构会是这样的:

在这里插入图片描述

各部分的意义如下:

  • TYPE:记录了value的类型,长度为一个字节,当服务器读入RDB文件中的键值对时,会根据value的值决定如何读入和解释value的数据,值可以是以下常量的其中一个:
    • 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
  • key:总是一个字符串对象,它的编码方式和REDIS_RDB_TYPE_STRING类型的value一样
  • value:根据TYPE类型的不同,以及保存内容长度的不同,保存的value的结构和长度也会有所不同
  • EXPIRETIME_MS:常量的长度为一个字节,它告诉读入程序,接下来要读入的将是一个以毫秒为单位的过期时间
  • ms:一个8字节长的带符号证书,记录着一个以毫秒为单位的UNIX时间戳,这个时间戳就是这个键值对的过期时间

例如:

在这里插入图片描述

2.3,value编码

RDB文件中的每个value部分都保存了一个值对象,每个值对象的类型都由与之对应的TYPE记录,根据类型不同,value的长度与结构也都不同

2.3.1,字符串对象

如果TYPE的值是REDIS_RDB_TYPE_STRING,那么value保存的就是一个字符串对象,字符串对象的编码可以为:

  • REDIS_ENCODING_INT
  • REDIS_ENCODING_RAW

REDIS_ENCODING_INT

如果字符串对象的编码为:REDIS_ENCODING_INT,那么说明保存的是长度不超过32位的整数,这种编码的对象将会按照下图的结构进行存储(假设字符串对象中保存的是用8位来保存的整数123):
在这里插入图片描述

REDIS_ENCODING_RAW

如果字符串编码为:REDIS_ENCODING_RAW,那么说明这个对象所保存的是一个字符串值,根据字符串长度的不同,有压缩和不压缩两种方法进行保存:

  • 如果字符串的长度小于等于20字节,字符串会被原样保存
  • 如果字符串的长度大于20字节,那么这个字符串会被压缩后再进行保存

【值得一提的是:只有当服务器打开了RDB文件压缩功能时才会出现上述的情况;否则RDB程序总会以无压缩的方式保存字符串值】

如果是以不压缩的方式进行保存的话:

在这里插入图片描述

  • string:保存了字符串本身
  • len:保存了字符串值的长度

如果是以压缩的方式进行保存的话,RDB程序会用以下的结构进行保存:
在这里插入图片描述

  • REDIS_RDB_ENC_LZF:表示字符串已经被LZF算法压缩过;读入程序碰到这个常量后,会根据之后的compressed_len、origin_len、compressed_string三部分,对字符串进行解析
  • compressed_len:字符串压缩过后的长度
  • origin_len:字符串原来的长度
  • compressed_string:被压缩后的字符串

2.3.2,列表对象

如果TYPE的值是REDIS_RDB_TYPE_LIST,那么value保存的就是一个REDS_ENCODING_LINKEDLIST编码的列表对象,RDB文件保存这种对象的结构如下:

在这里插入图片描述

list_length记录了列表的长度,代表列表保存了多少个项,读入程序可以根据这个知道应该读入多少个列表项。以一个包含三个元素的列表为例:
在这里插入图片描述

  • 第一个数字3是列表的长度,之后跟着的是三个列表项
  • 第一个列表项的长度为5,内容为字符串“hello”
  • 第二个列表项的长度为5,内容为字符串“world”
  • 第三个列表项的长度为1,内容为字符串“!”

2.3.3,集合对象

如果TYPE的值是REDIS_RDB_TYPE_SET,那么value保存的就是一个REDIS_ENCODING_HT编码的集合对象,RDB文件保存这种对象的结构如下:

在这里插入图片描述

  • set_size:集合的大小,记录了集合保存多少个元素
  • elemX:集合项,因为每个集合元素都是字符串对象,所以程序会以处理字符串对象的方式来保存和读入集合元素

例如有一个包含四个元素的集合:
在这里插入图片描述

  • 第一个数字4,表示有四个元素
  • 第一个元素的长度为5,存储的内容是:”apple“
  • 第二个元素的长度为6,存储的内容是:”banana“
  • 第三个元素的长度为3,存储的内容是:”cat“
  • 第四个元素的长度为3,存储的内容是:”dog“

2.3.4,有序集合对象

如果TYPE的值为REDIS_RDB_TYPE_ZSET,那么value保存的就是一个REDIS_ENCODING_SKIPLIST编码的有序集合对象,RDB文件保存这种对象的结构如下所示:

在这里插入图片描述

  • sorted_set_size:有序集合的大小,表示这个有序集合保存了多少元素
  • elementX:有序集合中的元素,每个元素又分为成员(member)与分值(score),成员是一个字符串对象,分值则是一个double类型的浮点数。程序在存储分值时,会将其转为字符串对象,再进行保存。

再细分下,能得到下图:

在这里插入图片描述

例如有一个带有两个元素的有序集合:

在这里插入图片描述

  • 第一个数字2表示有序集合中保存了两个元素
  • 第一个集合项的成员长度为2,内容为:”pi“,分值被转换成字符串之后变成了长度为4的字符串:”3.14“
  • 第二个集合项的成员长度为1,内容为:”e“,分值被转换成字符串之后变成了长度为3的字符串:”2.7“

2.3.5,哈希对象

如果TYPE的值为REDIS_RDB_TYPE_HASH,那么value保存的就是一个REDIS_ENCODING_HT编码的集合对象,RDB保存这种对象的结构如下图所示:

在这里插入图片描述

  • hash_size:哈希表的大小,表示哈希表保存了多少键值对
  • key_value_pair X:代表哈希表中的键值对,键值对中的键和值都是字符串对象,所以程序会以处理字符串对象的方式来保存和读入键值对

结构中的每个键值对都以键紧挨着值的方式排列在一起,所以可以细分为:
在这里插入图片描述

假设有一个保存着两个键值对的哈希表:

在这里插入图片描述

  • 第一个数字2,记录了哈希表的键值对数量
  • 第一个键值对的键长度为1,保存的字符串内容为:“a”;值是长度为5的字符串“apple”
  • 第二个键值对的键长度为1,保存的字符串内容为:“b”;值是长度为6的字符串“banana”

2.3.6,INSET编码的集合

如果TYPE的值为REDIS_RDB_TYPE_SET_INTSET,那么value保存的就是一个整数集合对象,RDB文件保存这种对象的方法是,先将整数集合转换为字符串对象,然后将这个字符串对象保存到RDB文件中

在读入RDB文件的过程中,如果遇到由整数集合转换而得来的字符串对象,那么程序会根据TYPE值,先读入字符串对象,再将其转换为原来的整数集合对象

2.3.7,ZIPLIST编码的列表、哈希表或者有序集合

如果TYPE的值是以下几种之一:

  • REDIS_RDB_TYPE_LIST_ZIPLIST
  • REDIS_RDB_TYPE_HASH_ZIPLIST
  • REDIS_RDB_TYPE_ZSET_ZIPLIST

那么value保存的就是一个压缩列表,RDB保存着类对象的方法是:

  1. 将压缩列表转换为一个字符串对象
  2. 将转换所得的字符串对象保存到RDB文件中

在读入RDB文件时,如果遇到这种情况产生的字符串对象时,程序会根据TYPE值的指示,执行以下操作:

  • 读入字符串对象,将其转换为原来的压缩列表对象
  • 根据TYPE的值,设置压缩列表对象的类型:
    • 如果TYPE的值为:REDIS_RDB_TYPE_LIST_ZIPLIST,那么压缩列表对象的类型为列表
    • 如果TYPE的值为:REDIS_RDB_TYPE_HASH_ZIPLIST,那么压缩列表对象的类型为哈希表
    • 如果TYPE的值为:REDIS_RDB_TYPE_ZSET_ZIPLIST,那么压缩列表对象的类型为有序集合
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redis是一个开源的内存数据存储系统,可以用作数据库、缓存和消息队列等。它支持多种数据结构,如字符串、列表、哈希、集合和有序集合等。 在Redis中,RDB文件是一种持久化的方式,用于将内存中的数据保存到硬盘中。当我们使用RDB文件进行启动时,Redis会将RDB文件加载到内存中,从而恢复原来的数据状态。 RDB文件是通过Redis快照功能生成的,可以通过执行SAVE或BGSAVE命令手动创建RDB文件,也可以根据配置文件中设置的自动快照触发条件周期性地创建RDB文件。 当我们通过RDB文件启动Redis时,首先需要将RDB文件放在Redis的工作目录下。然后,在启动Redis时,可以通过命令行的方式指定RDB文件的路径,例如: redis-server /path/to/redis.conf --dir /path/to/rdb/file 这样,Redis就会加载RDB文件,并将其中的数据恢复到内存中。启动完成后,Redis将可以使用之前保存在RDB文件中的数据。 通过RDB文件启动Redis的优点是恢复速度快,因为RDB文件保存了Redis的快照,加载RDB文件只需要将文件中的数据读取到内存中即可。同时,RDB文件的大小相对较小,占用的磁盘空间较少。 需要注意的是,使用RDB文件进行启动时,最好先备份好最新的RDB文件,以免数据丢失。另外,RDB文件只保存了快照时刻的数据,因此如果在最新RDB文件生成之后有新数据写入,这部分数据是无法恢复的。为了避免数据丢失,还可以将AOF日志功能与RDB文件一起使用,将数据的修改操作追加到AOF日志文件中,确保数据的持久性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值