一文读懂Redis常见对象类型的底层数据结构
Posted Java笔记虾
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一文读懂Redis常见对象类型的底层数据结构相关的知识,希望对你有一定的参考价值。
Redis
是一个基于内存中的数据结构存储系统,可以用作数据库、缓存和消息中间件。Redis
支持五种常见对象类型:字符串(String
)、哈希(Hash
)、列表(List
)、集合(Set
)以及有序集合(Zset
),我们在日常工作中也会经常使用它们。知其然,更要知其所以然,本文将会带你读懂这五种常见对象类型的底层数据结构。
本文主要内容参考自《Redis设计与实现》
对象类型和编码
Redis
使用对象来存储键和值的,在Redis
中,每个对象都由redisObject
结构表示。redisObject
结构主要包含三个属性:type
、encoding
和ptr
。
typedef struct redisObject {
// 类型
unsigned type:4;
// 编码
unsigned encoding:4;
// 底层数据结构的指针
void *ptr;
} robj;
其中type
属性记录了对象的类型,对于Redis
来说,键对象总是字符串类型,值对象可以是任意支持的类型。因此,当我们说Redis
键采用哪种对象类型的时候,指的是对应的值采用哪种对象类型。
*ptr
属性指向了对象的底层数据结构,而这些数据结构由encoding
属性决定。
之所以由encoding
属性来决定对象的底层数据结构,是为了实现同一对象类型,支持不同的底层实现。这样就能在不同场景下,使用不同的底层数据结构,进而极大提升Redis
的灵活性和效率。
底层数据结构后面会详细讲解,这里简单看一下即可。
字符串对象
字符串是我们日常工作中用得最多的对象类型,它对应的编码可以是int
、raw
和embstr
。
如果一个字符串对象保存的是不超过long
类型的整数值,此时编码类型即为int
,其底层数据结构直接就是long
类型。例如执行set number 10086
,就会创建int
编码的字符串对象作为number
键的值。
如果字符串对象保存的是一个长度大于39字节的字符串,此时编码类型即为raw
,其底层数据结构是简单动态字符串(SDS
);如果长度小于等于39个字节,编码类型则为embstr
,底层数据结构就是embstr
编码SDS
。下面,我们详细理解下什么是简单动态字符串。
简单动态字符串
SDS定义
在Redis
中,使用sdshdr
数据结构表示SDS
:
struct sdshdr {
// 字符串长度
int len;
// buf数组中未使用的字节数
int free;
// 字节数组,用于保存字符串
char buf[];
};
SDS
遵循了C字符串以空字符结尾的惯例,保存空字符的1字节不会计算在len
属性里面。例如,Redis
这个字符串在SDS
里面的数据可能是如下形式:
SDS与C字符串的区别
C语言使用长度为N+1
的字符数组来表示长度为N
的字符串,并且字符串的最后一个元素是空字符