Redis(三):有序集合底层实现,java架构师面试答案

Redis的有序集合利用跳跃表(Skip List)作为底层数据结构,通过zskiplistNode结构定义节点,包含后退指针、分值、成员对象等。跳跃表的层依据幂次定律随机生成,每个节点的前进指针用于查找,跨度记录相邻节点间距离,用于计算节点排名。后退指针支持反向遍历,节点按分值排序,分值相同则按成员对象排序。
摘要由CSDN通过智能技术生成

跳跃表结点由redis.h/zskiplistNode结构定义

typedef struct zskiplistNode{

//后退指针

struct zskiplistNode *backward;

//分值key

double score;

//成员对象value

robj *obj;

//层(也是一个结构体,不过是一个数组)

struct zskiplistLevel{

//前进指针

struct zskiplistNode *forward;

//跨度

unsigned int span;

}l

《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》

【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享

evel[];

}zskiplistNode;

跳跃表结点的level数组可以包含多个元素(不过越前面的结点,包含的元素一般会更多,因为要保证符合跳跃表的要求,即每一层的索引链表必须是下一层的索引链表的子集),一般来说,层越高,找元素的效率就越快。

每次创建一个结点的时候,redis会根据幂次定律(越大的数出现的机率越小)随机生成一个介于1和32之间的值,作为Level数组的大小(也就是这个结点的所拥有的索引高度,即上面有多少个索引链表会可以找到他)

前进指针

每个层里面的元素都有一个指向表尾的指针,用来找到下一个结点(对比key后,发现小了,要往前找,如果碰到NULL,就代表元素不存在)。

跨度

记录两个结点间的距离

  • 两个结点之间的跨度越大,相距就越远

  • 指向NULL的前进指针的跨度都为0

其实跨度的用途是用来计算结点的排位(rank)的,也就是结点的位置,排在最底层的第几个,找到结点的路径遇到的所有层的所有跨度加起来就是结点的排位。

后退指针

每个结点都有后退指针,用来从表尾遍历到表头的。

分值和成员

结点的分值就是存储键值对的value值,是一个double类型的浮点数,结点的顺序是按照value的大小来进行排序的(所以value必须可以解析为浮点型,而且必须唯一,如果重复的话会发生替换)

结点的成员对象是一个指针,指向的对象是一个sds对象(之前提到的SDS字符串),用来储存键值对的key值。

跳跃表

多个跳跃结点就可以形成跳跃表,并且仅仅通过一个zskiplist结构来持有这些跳跃结点。

typedef struct zskiplist{

//表头结点和表尾结点

struct skiplistNode *header,*tail;

//表中结点数量

unsigned long length;

//表中层数最大结点的层数(即拥有的索引链表数量)

int level;

}zskiplist;

header和tail指针分别指向跳跃表的表头和表尾结点,通过这两个指针,程序找到第一个结点和最后一个结点的时间复杂度都为 O ( 1 ) O(1) O(1),并且得到跳跃表的结点个数或者长度,直接返回length即可,时间复杂度也为 O ( 1 ) O(1) O(1)。

注意,LEVEL属性是不包括傀儡结点的,傀儡结点里面的数组有很多元素结点没有形成链表,即跨度为0

重点
  • 跳跃表是有序集合的底层实现之一
  • Redis的跳跃表由zskiplist和zskiplistNode组成,前者保存跳跃表信息,后者是跳跃表结点
  • 每个跳跃表结点的层高为1~32
  • 同一个跳跃表中,多个结点可以包含相同的分值(即score可以相同,score必须可以转化为浮点型!),但每个结点的成员对象(一个sds字符串)必须唯一(member必须唯一,出现重复会重置)
  • 跳跃表的结点按照分值进行排序,如果出现分值相同,就按照成员对象的大小进行排序
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值