Redis底层数据结构
Redis没有表的概念,Redis实例所对应的db以编号区分,db本身就是key的命名空间。
RedisObject
typedef struct redisObject{
unsigned type:4 ; // 五种对象类型
unsigned encodeing:4; //编码
void *ptr; //指向底层实现数据结构的指针
int refcount; //引用计数
unsigned lru:LRU_BITS; // 记录最后一次被命令程序访问的时间
}
一、字符串对象
C语言:字符串数据 以"\0"结尾
Redis 使用SDS ,简单动态字符串
struct sdshdr{
// 记录已经使用的字节数
int len;
// 数组中未使用的字节数量
int free;
// 字节数组
char buf[];
}
SDS的优势:
-
SDS在C字符串的基础上加了 len 和 free ,SDS可以在O(1)的时间内获取到字符串长度(len+free+1)
-
SDS由于记录了长度,在可能造成缓冲区溢出时自动重新分配内存,杜绝了缓冲区溢出
-
可以存取二进制数据
使用场景:
存储字符串和整型数据、存储key、AOF缓冲区和用户输入缓冲
二、跳跃表
是有序集合的底层实现(sorted-set)
将有序的链表中的部分节点分层,每一层都是一个有序链表
查找:
在查找时优先从最高层开始向后查找,当到达某个节点是,如果next节点值大于要查找的值或者next指针指向null,则从当前节点下降一层继续向后找。
如上图:我们查找节点7时,如果没有跳表,需要经过7次查询。
但是最终经过两层的抽取,只需要3次查找即可。具有二分查找的功能。
插入:
理想跳跃表
通过抛硬币的方式来决定插入节点跨越的层数。
通过计算次数达到1/2概率
删除:
在每层找到该元素并删除
特点:
-
每层都是一个有序链表
-
查找次数近似与层数
-
最底层包含所有元素
-
空间换时间 空间复杂度 O(n)
Redis跳跃表的实现:
typedef struct zskiplistNode{
sds ele;
double score; // 存储排序的分值
struct zskiplistNode *backward; // 后退指针,指向当前节点最底层的前一个节点
/**
柔性数组
*/
struct zskiplistLevel