redis跳跃表

Redis使用跳跃表作为有序集合键的底层实现之一,同时Redis是在集群节点内用作内部数据结构。

跳跃表的实现

Redis的跳跃表由redis.h/zskiplistNode和redis.h/zskiplist两个结构定义,其中zskiplistNode结构⽤于表⽰跳跃表节点,⽽zskiplist结构则⽤于保存跳跃表节点的相关信息,⽐如节点的数量,以及指向表头节点和表尾节点的指针等等。

skiplist

对于zskiplist结构:

  • header指向表头节点,tail指向表尾节点
  • level表示当前跳跃表中,层数最大
    的那个节点的层数。(表头节点不算,层数指图中L的个数)
  • length记录跳跃表长度,不计表头节点。
typedef struct zskiplist {
//表头节点和表尾节点
structz skiplistNode *header, *tail;
//表中节点的数量
unsigned long length;
//表中层数最⼤的节点的层数
int level;
} zskiplist;

zskiplistNode

对于zskiplistNode结构:

  • level []:构成节点的各个层,每个层定义有两个属性:forward和span,代表前进指针和跨度,上图中箭头上的数字就是跨度,代表从这个层到另一个节点的层跨过的节点数。当程序从表头节点向后遍历时,会通过该指针访问下一个节点。
    • 每次创建⼀个新跳跃表节点的时候,程序都根据幂次定律(powerlaw,越⼤的数出现的概率越⼩)随机⽣成⼀个介于1和32之间的值作为level数组的⼤⼩,这个⼤⼩就是层的“⾼度”。
    • 一般来说,层越多,访问其他节点的速度越快。
    • level[x].forward
    • level[x].span
      • 跨度,用于记录两节点之间的距离,跨度是⽤来计算排位(rank)的:在查找某个节点的过程中,将沿途访问过的所有层的跨度累计起来,得到的结果就是⽬标节点在跳跃表中的排位。
  • backward:后退指针。上图中BW即为后退指针,指向前一个节点。
    • 与前进指针一次性跳过多个节点不同,后退指针只能挨个后退,直到null结束。
  • score:分值。是一个double浮点数,上图中1.0、2.0、3.0是当前节点保存的分值,节点在跳跃表中以该分值按序排列。
  • obj:成员对象指针。各个节点保存的内容,上图中o1,o2,o3即为对象。
    • 指向字符串对象,字符串对象保存一个SDS值。
    • 在同一个跳跃表中,各节点保存的成员对象一定不相同,但分值可以相同,各节点按分值从小到大排列,分值相同的按成员对象在字典序中的大小排列。
typedef struct zskiplistNode {
	struct zskiplistNode *backward; // 后退指针
	double score; // 分度值
	robj *obj; // 成员对象
	struct zskiplistLevel {
		struct zskiplistNode *forward; // 前进指针
		unsigned int span; // 跨度
	} level []; // 层 
} zskiplist;

posted @ 2023-03-19 21:04  新游  阅读(77)  评论(0)    收藏  举报