跳跃表(skiplist)
定义
-
在每个节点中维持多个指向其他节点的指针以快速访问节点的一种有序数据结构
-
有序集合键的底层实现之一
适用场景
-
一个有序集合包含的元素数量比较多,又或者有序集合中元素的成员(member)是比较长的字符串
-
在集群节点中用作内部数据结构
跳跃表结点
1 | // 跳跃表结点 |
层(Level 数组)
-
原理:包含多个元素,每个元素包含一个指向其他节点的指针,以加快访问其他节点的速度。一般来说,其访问其他节点的速度与层数正相关。
-
高度:每次创建一个新跳跃表节点的时候,程序都根据幂次定律(power law,越大的数出现概率越小)随机生成一个介于 1 和 32 之间的值作为 level 数组的大小
前进指针(level [i].forward 属性)
-
def 从表头向表尾方向访问节点的指针
- 一次可以跳过多个成员
-
用于执行有序集合的遍历操作
跨度(level [i].span 属性)
-
def 两个节点之间的距离
- 跨度越大,间距越远
-
注:指向 Null 的所有前进指针的跨度都为 0,因未连向任何节点
-
用于计算有序集合中成员的排名(rank)
后退指针(level [i].backward 属性)
-
def 从表尾向表头方向访问节点的指针
- 每个节点只有一个后退指针,这也意味着每次只能通过顺序回退的方式到达有序集合的前一节点,以向前遍历
分值(level [i].score 属性)
-
def double 类型的浮点数
- 所有节点按照分值从小到大来排序
成员(level [i].obj 属性)
-
def 指向字符串对象的指针,指向的对象中保存着一个 SDS 值
-
在同一个跳跃表中,各个节点保存的成员对象必须是唯一的;多个节点保存的分值可以相同
-
分值相同的节点将按照成员对象在字典序中的大小来进行排序,成员对象较小的节点会排在前面(靠近表头的方向),而成员对象较大的节点则会排在后面(靠近表尾的方向)
跳跃表
1 | // 跳跃表 |
执行下述操作的时间复杂度均为 O (1):
-
程序定位表头节点和表尾节点:header 和 tail 指针分别指向跳跃表的表头和表尾节点
-
返回跳跃表的长度:使用 length 属性来记录节点的数量
-
获取跳跃表中层高最大的那个节点的层数量:使用 level 属性,注:表头节点的层高并不计算在内
有序集合(zset)操作
常用命令
1 | import redis |
范围性数据的获取与删除命令
1 | # ZREVRANK:返回有序集合中成员的排名 |
并集与交集命令
1 | conn.zadd('zset_key2', 'a', 1, 'b', 2, 'c', 3) |

1 | # ZUNIONSTORE:对给定有序集合进行并集运算 |

【参考】
[1] 《Redis 的设计与实现》
[2] 《Redis 实战》