Redis底层数据结构一共有 6 种,分别是简单动态字符串、双向链表、压缩列表、哈希表、跳表和整数数组。它们和数据类型的对应关系如下图所示:
OBJECT ENCODING key 该命令是用来显示那五大数据类型的底层数据结构。
String数据结构类型
Redis使用了SDS作为默认的字符串表示,SDS是简单动态字符串(Simple Dynamic String)的缩写。SDS结构如下所示:
struct sdshdr {
int len; //buf已使用的长度
int free; //buf未使用的长度
char buf[]; //buf表示字节数组,用来存储字符串
};
-
Redis 为什么要重新定义SDS 去存储string呢?
1、c语言没有string类型, 只有char[],且char[]必须先分配空间长度;
2、获取char[]的长度,需要遍历数组,len(char[])时间复杂度O(n);
3、char[]预先分配了长度,数据增长后需要扩容;
4、c语言的char数组,用'\0'代表结束,意味着存储二进制数据不能包含'\0',图片音频等用二进制存储会有问题——这就是为什么Redis说自己实现的SDS是二进制安全的字符串。
通过SDS的结构可以看出,buf数组的长度=free+len+1(其中1表示字符串结尾的空字符);所以,一个SDS结构占据的空间为:free所占长度+len所占长度+ buf数组的长度=4+4+free+len+1=free+len+9。
4 字节的 len,可表示的字符串长度为
2^32-1
,在实际应用中,存放于 Redis 中的字符串往往没有这么长,没有必要每个字符串都让 len 和 free 为 4 字节。
简单动态字符串SDS,字符串对象的编码可以是int,raw或者embstr。
- int 编码:保存的是可以用 long 类型表示的整数值。
- raw 编码:保存长度大于44字节的字符串(redis3.2版本之前是39字节,之后是44字节),可分配多次内存空间
- embstr 编码:保存长度小于44字节的字符串(redis3.2版本之前是39字节,之后是44字节)存储简短字符串,一次的内存分配;它是只读的,如果对内容进行修改,就会变成raw编码(即使没超过44字节);
- 关于redis3.2版本之前embstr转成raw的条件为什么长度是44?
首先这里要介绍下Redis的存储结构,其中所有对象都可以由redisObject结构来表示,可以参考我这篇博客:Redis第七讲 Redis存储模型详解
redisObject 占 16 个字节,当 buf 数组内的字符串长度是 39 时,sdshdr 的大小为 4+4+39+1&