💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。
- 持续学习,不断总结,共同进步,活到老学到老
- 人生的本质是追寻自我的提升,包括思想、能力、意志等等。
- 直面变化,找到背后更基础的东西,更基础的东西是用户的需求。
- 我们的成功是我们的现在和将来决定的。今天和明天已经由昨天决定,你还可以决定后天。
非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨
博客目录
9.TYPE 字段与 value 的编码
RDB 文件中的每个 value 部分都保存了一个值对象,每个值对象的类型都由与之对应的 TYPE 记录,根据类型的不同,value 部分的结构、长度也会有所不同
1.字符串对象
如果 TYPE 的值为 REDIS_RDB_TYPE_STRING,那么 value 保存的就是一个字符串对象,字符串对象的编码可以是 REDIS_ENCODING_INT 或者 REDIS_ENCODING_RAW
① 如果字符串对象的编码为 REDIS_ENCODING_INT:
那么说明对象中保存的是长度不超过 32 位的整数,这种编码的对象将以下图所示的结构保存
其中,ENCODING 的值可以是 REDIS_RDB_ENC_INT8、REDIS_RDB_ENC_INT16 或者 REDIS_RDB_ENC_INT32 三个常量的其中一个,它们分别代表 RDB 文件使用 8 位(bit)、16 位或者 32 位来保存整数值 integer。
② 如果字符串对象的编码为 REDIS_ENCODING_RAW:
那么说明对象所保存的是一个字符串值,根据字符串长度的不同,有压缩和不压缩两种方法来保存这个字符串:
- 如果字符串的长度小于等于 20 字节,那么这个字符串会直接被原样保存
- 如果字符串的长度大于 20 字节,那么这个字符串会被压缩之后再保存
备注:以上两个条件是在假设服务器打开了 RDB 文件压缩功能的情况下进行的,如果服务器关闭了 RDB 文件压缩功能,那么 RDB 程序总以无压缩的方式保存字符串值,对于没有被压缩的字符串,RDB 程序会以下图所示的结构来保存该字符串
- string 部分保存了字符串值本身
- len 保存了字符串值的长度
对于压缩后的字符串,RDB 程序会以下图所示的结构来保存该字符串
其中,REDIS_RDB_ENC_LZF
常量标志着字符串已经被 LZF 算法(http://liblzf.plan9.de)压缩过了,读入程序在碰到这个常量时,会根据之后的compressed_len、origin_len和compressed_string三部分,对字符串进行解压缩:其中compressed_len记录的是字符串被压缩之后的长度,而origin_len记录的是字符串原来的长度,compressed_string记录的则是被压缩之后的字符串。
2.列表对象
如果 TYPE 的值为 REDIS_RDB_TYPE_LIST
,那么 value 保存的就是一个 REDIS_ENCODING_LINKEDLIST
编码的列表对象。
RDB 文件保存这种对象的结构如下图所示:
- list_length 记录了列表的长度,它记录列表保存了多少个项(item),读入程序可以通过这个长度知道自己应该读入多少个列表项
- 图中以 item 开头的部分代表列表的项,因为每个列表项都是一个字符串对象,所以程序会以处理字符串对象的方式来保存和读入列表项
示例
- 第一个列表项的长度为 5,内容为字符串"hello"。
- 第二个列表项的长度也为 5,内容为字符串"world"。
- 第三个列表项的长度为 1,内容为字符串"!"
3.集合对象
如果 TYPE 的值为 REDIS_RDB_TYPE_SET
,那么 value 保存的就是一个 REDIS_ENCODING_HT
编码的集合对象,RDB 文件保存这种对象的结构如下图所示:
- set_size 是集合的大小,它记录集合保存了多少个元素,读入程序可以通过这个大小知道自己应该读入多少个集合元素。
- 以 elem 开头的部分代表集合的元素,因为每个集合元素都是一个字符串对象,所以程序会以处理字符串对象的方式来保存和读入集合元素。
4.哈希表对象
如果 TYPE 的值为 REDIS_RDB_TYPE_HASH
,那么 value 保存的就是一个 REDIS_ENCODING_HT
编码的集合对象,RDB 文件保存这种对象的结构如下图所示:
- hash_size 记录了哈希表的大小,也即是这个哈希表保存了多少键值对,读入程序可以通过这个大小知道自己应该读入多少个键值对。
- 以 key_value_pair 开头的部分代表哈希表中的键值对,键值对的键和值都是字符串对象,所以程序会以处理字符串对象的方式来保存和读入键值对。
结构中的每个键值对都以键紧挨着值的方式排列在一起,如下图所示:
因此,从更详细的角度看,哈希表对象的结构可以表示为下图所示:
作为示例,下图展示了一个包含两个键值对的哈希表,第一个数字 2 记录了哈希表的键值对数量,之后跟着的是两个键值对:
- 第一个键值对的键是长度为 1 的字符串"a",值是长度为 5 的字符串"apple"
- 第二个键值对的键是长度为 1 的字符串"b",值是长度为 6 的字符串"banana"
5.有序集合对象
如果 TYPE 的值为 REDIS_RDB_TYPE_ZSET
,那么 value 保存的就是一个 REDIS_ENCODING_SKIPLIST
编码的有序集合对象,RDB 文件保存这种对象的结构如下图所示:
sorted_set_size
记录了有序集合的大小,也即是这个有序集合保存了多少元素,读入程序需要根据这个值来决定应该读入多少有序集合元素。以 element 开头的部分代表有序集合中的元素,每个元素又分为成员(member)和分值(score)两部分,成员是一个字符串对象,分值则是一个 double 类型的浮点数,程序在保存 RDB 文件时会先将分值转换成字符串对象,然后再用保存字符串对象的方法将分值保存起来。
有序集合中的每个元素都以成员紧挨着分值的方式排列,下图所示:
因此,从更详细的角度看,有序集合对象的结构可以表示为下图所示:
作为示例,下图展示了一个带有两个元素的有序集合,第一个数字 2 记录了有序集合的元素数量,之后跟着的是两个有序集合元素:
- 第一个元素的成员是长度为 2 的字符串"pi",分值被转换成字符串之后变成了长度为 4 的字符串"3.14"
- 第二个元素的成员是长度为 1 的字符串"e",分值被转换成字符串之后变成了长度为 3 的字符串"2.7"
6.INTSET 编码的集合
- 如果
TYPE
的值为REDIS_RDB_TYPE_SET_INTSET
,那么 value 保存的就是一个整数集合对象 RDB
文件保存这种对象的方法是,先将整数集合转换为字符串对象,然后将这个字符串对象保存到RDB
文件里面- 如果程序在读入
RDB
文件的过程中,碰到由整数集合对象转换成的字符串对象,那么程序会根据TYPE
值的指示,先读入字符串对象,再将这个字符串对象转换成原来的整数集合对象
7.ZIPLIST 编码的列表、哈希表或者有序集合
- 如果
TYPE
的值为REDIS_RDB_TYPE_LIST_ZIPLIST
、REDIS_RDB_TYPE_HASH_ZIPLIST
或者REDIS_RDB_TYPE_ZSET_ZIPLIST
, - 那么 value 保存的就是一个压缩列表对象,
RDB
文件保存这种对象的方法是:- 将压缩列表转换成一个字符串对象
- 将转换所得的字符串对象保存到
RDB
文件。
- 如果程序在读入
RDB
文件的过程中,碰到由压缩列表对象转换成的字符串对象,那么程序会根据TYPE
值的指示,执行以下操作:- 读入字符串对象,并将它转换成原来的压缩列表对象
- 根据 TYPE 的值,设置压缩列表对象的类型:
- 如果 TYPE 的值为
REDIS_RDB_TYPE_LIST_ZIPLIST
,那么压缩列表对象的类型为列表; - 如果 TYPE 的值为
REDIS_RDB_TYPE_HASH_ZIPLIST
,那么压缩列表对象的类型为哈希表; - 如果 TYPE 的值为
REDIS_RDB_TYPE_ZSET_ZIPLIST
,那么压缩列表对象的类型为有序集合; - 从这个步骤可以看出,由于 TYPE 的存在,即使列表、哈希表和有序集合三种类型都使用压缩列表来保存,RDB 读入程序也总可以将读入并转换之后得出的压缩列表设置成原来的类型
觉得有用的话点个赞
👍🏻
呗。
❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍
🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙