深入理解Redis数据结构—跳跃表

跳跃表是一种有序的数据结构,通过在每个节点中维持多个指向其他节点的指针,从而实现快速访问节点;

      跳跃表支持平均O(logN)、最坏O(N)复杂度的节点查找,还可以通过顺序性操作来批量处理节点;

      Redis使用跳跃表作为有序集合建(ZSet)的底层实现之一;若一个有序集合包含的元素数量较多,或有序集合中元素的成员是较长字符串时,Redis就会使用跳跃表作为有序集合键的底层实现;

      Redis只在两个地方使用到了跳跃表:① 有序集合键的底层实现、② 集群节点中用作内部数据结构

跳跃表的实现

      Redis的跳跃表由redis.h/zskiplistNode和redis.h/zskiplist两个结构定义,zskiplistNode结构表示跳跃表节点,zskiplit结构用于保存跳跃表节点的相关信息

深入理解Redis数据结构—跳跃表_第1张图片

      zskiplist结构如下:

  • header:指向跳跃表的表头节点;
  • tail:指向跳跃表的表尾节点;
  • level:记录跳跃表内,层数最大的节点的层高(不包括表头节点);
  • length:记录跳跃表长度,跳跃表目前包含的节点的数量(不包括表头节点);

zskiplistNode结构如下:

  • level[ ]:每层都有前进指针跨度两个属性,前进指针用于指向表尾方向的其他节点的指针,跨度则记录了该前进指针指向的目标节点与当前节点的距离;
  • BW(后退指针):指向表头方向的上一个节点;
  • 分值:保存了每个节点的分值;
  • 成员对象(obj):指向节点所保存的成员对象;

跳跃表节点

      zskiplistNode结构定义:

深入理解Redis数据结构—跳跃表_第2张图片

      1、level:创建新跳跃表节点时,程序都根据幂次定律随机生成一个介于1~32之间的值作为level数组的大小,该大小即为层高;每层都包含一个前进指针,层数越多访问其他节点速度越快

      2、跨度:层的跨度(level[i].span)用于记录两节点之间的距离;两节点之间的跨度越大,相距就越远;指向NULL的所有前进指针的跨度都为0,没有连向任何节点;用于计算节点在跳跃表中的排位,查找某个节点的过程中,将沿途访问过的所有层的跨度累加起来,结果就是目标节点在跳跃表中的排位

      3、后退指针用于从表尾向表头方向访问节点,每次只能后退至前一个节点;

      4、节点分值和成员对象:分值是一个double类型的浮点数,跳跃表中的所有节点都按分值从小到大排序;成员对象是一个指针,指向一个字符串对象,字符串对象保存着一个SDS值;

      在同一个跳跃表中,各节点保存的成员对象必须是唯一的,但多个节点保存的分值可以相同,分值相同的节点按照成员对象在字典序中的大小来进行排序,成员对象较小的节点会排在靠近表头方向的位置,成员对象较大的对象会排在靠近表尾的位置;

你可能感兴趣的:(redis,数据结构,java)