概 述
我们平时用 Redis都是处于用户层面,我们可能会不加思索地操作一个 key-value 对来方便地存取数据,感觉方便之至。但你知道这些数据在背后是如何存储以及编码的吗? 了解清楚了这个问题,将对我们更加高效地使用 Redis具有指导意义。本文开始我们将结合 Redis源码来逐个探讨Redis五大数据类型的内部编码机制。
实验环境:Redis 4.0.10
注:本文首发于 My 公众号CodeSheep,可长按或扫描下面的小心心来订阅 ↓ ↓ ↓
Redis 数据类型内部编码概况
对于 Redis的常用5种数据类型(String、Hash、List、Set、sorted set),每种数据类型都提供了最少两种内部的编码格式,而且每个数据类型内部编码方式的选择对用户是完全透明的,Redis会根据数据量自适应地选择较优化的内部编码格式。
如果想查看某个键的内部编码格式,可以使用指令来进行,比如:
的每个键值内部都是使用一个名字叫做这个 C语言结构体保存的,其代码如下:
解释如下:
:表示键值的数据类型,包括 String、List、Set、ZSet、Hash
:表示键值的内部编码方式,从 Redis源码看目前取值有如下几种:
:表示该键值被引用的数量,即一个键值可被多个键引用
本文我们就从 Redis最基本的 String类型的内部编码开始探讨!
String 类型的内部编码情况
字符串是 Redis最基本的数据类型,Redis 中字符串对象的编码可以是,或者中的某一种,分别介绍如下:
int 编码:保存long 型的64位有符号整数
embstr 编码:保存长度小于44字节的字符串
raw 编码:保存长度大于44字节的字符串
我们不妨来做个实验实际看一下:
实际情况就是 Redis 内部会根据用户给的不同键值而使用不同的编码格式,而这一切对用户完全透明!
Redis 是使用SDS(“简单动态字符串”)这个结构体来存储字符串,代码里定义了5种SDS结构体:
可以看出,除了结构体字段数据类型的不同,其字段含义相差无几,其中:
:字符串的长度(实际使用的长度)
:分配内存的大小
:标志位,低三位表示类型,其余五位未使用
:字符数组
了解了这些基本的数据结构以后,我们就来看看上面例子中:
set foo 123
set foo abc
set foo abcdefghijklmnopqrstuvwxyzabcdeffasdffsdaadsx
这三种情形下 Redis 内部到底是怎么存数据的!
INT 编码格式
命令示例:
当字符串键值的内容可以用一个64位有符号整形来表示时,Redis会将键值转化为 long型来进行存储,此时即对应编码类型。
编码类型内部的内存结构可以形象地表示如下:
而且 Redis 启动时会预先建立10000个分别存储0~9999的 redisObject 变量作为共享对象,这就意味着如果 set字符串的键值在 0~10000 之间的话,则可以直接指向共享对象而不需要再建立新对象,此时键值不占空间!
因此,当执行如下指令时:
其实key1和key2这两个键值都直接引用了一个 Redis 预先已建立好的共享 redisObject 对象,就像下面这样:
源码之前,了无秘密,我们再对照下面的源码,来理解一下上述过程
EMBSTR 编码格式
命令示例:
Redis 在保存长度小于44字节的字符串时会采用编码方式,口说无凭,我们来瞅瞅源码:
从上述代码中很容易看出,对于长度小于 44的字符串,Redis 对键值采用方式,EMBSTR 顾名思义即:embedded string,表示嵌入式的String。从内存结构上来讲 即字符串 sds结构体与其对应的 redisObject 对象分配在同一块连续的内存空间,这就仿佛字符串 sds 嵌入在 redisObject 对象之中一样,这一切从下面的代码即可清楚地看到:
因此,对于指令所设置的键值,其内存结构示意图如下:
RAW 编码格式
指令示例:
正如指令示例,当字符串的键值为长度大于44的超长字符串时,Redis 则会将键值的内部编码方式改为格式,这与上面的编码方式的不同之处在于 此时动态字符串 sds 的内存与其依赖的 redisObject 的内存不再连续了,以上述命令为例,其键值的内存结构如下所示:
到此就讲完了最基本的String数据类型的内部编码情况,怎么样,还是挺好理解的吧!
后续我们将继续剖析 Redis 中 Hash 数据类型的内部编码格式。
后 记
由于能力有限,若有错误或者不当之处,还请大家批评指正,一起学习交流!
如果有兴趣,也可以抽时间看看作者关于容器化、微服务化方面的文章:
作者更多务实、能看懂、可复现的原创文章尽在公众号CodeSheep,欢迎订阅 ⬇️⬇️⬇️
你花了·来阅读
点个再走吧~
领取专属 10元无门槛券
私享最新 技术干货