但通过使用一个 zskiplist 结构来持有这些节点,程序可以更方便地对整个跳跃表进行处理,比如快速访问跳跃表的表头节点和表尾节点,又或者快速地获取跳跃表节点的数量(也即是跳跃表的长度)等信息,如下所示:

文章插图
zskiplist 结构的定义如下:
typedef struct zskiplist { // 表头节点和表尾节点 struct zskiplistNode *header, *tail; // 表中节点的数量 unsigned long length; // 表中层数最大的节点的层数 int level;} zskiplist;- header 和 tail 指针分别指向跳跃表的表头和表尾节点,通过这两个指针,程序定位表头节点和表尾节点的复杂度为 O(1)。
- 通过使用 length 属性来记录节点的数量,程序可以在 O(1) 复杂度内返回跳跃表的长度 。
- level 属性则用于在 O(1) 复杂度内获取跳跃表中层高最大的那个节点的层数量,注意表头节点的层高并不计算在内 。

文章插图
面试:为啥 redis 使用跳表(skiplist)而不是使用 red-black?
- skiplist的复杂度和红黑树一样,而且实现起来更简单 。
- 在并发环境下skiplist有另外一个优势,红黑树在插入和删除的时候可能需要做一些rebalance的操作,这样的操作可能会涉及到整个树的其他部分,而skiplist的操作显然更加局部性一些,所需要盯住的节点更少,因此在这样的情况下性能好一些 。
附:开发者说的为什么选用skiplist The Skip list

文章插图
总结
- 跳跃表是有序集合的底层实现之一,除此之外它在 Redis 中没有其他应用 。
- Redis 的跳跃表实现由 zskiplist 和 zskiplistNode 两个结构组成,其中 zskiplist 用于保存跳跃表信息(比如表头节点、表尾节点、长度),而 zskiplistNode 则用于表示跳跃表节点 。
- 每个跳跃表节点的层高都是 1 至 32 之间的随机数 。
- 在同一个跳跃表中,多个节点可以包含相同的分值,但每个节点的成员对象必须是唯一的 。
- 跳跃表中的节点按照分值大小进行排序,当分值相同时,节点按照成员对象的大小进行排序 。
http://redisbook.com/preview/skiplist/datastruct.html
文章持续更新,可以公众号搜一搜「 一角钱技术 」第一时间阅读,本文 GitHub org_hejianhui/JAVAStudy 已经收录,欢迎 Star 。
推荐阅读
- 八张图了解Redis和MySQL数据一致性问题
- Nginx可以做什么?看完这篇你就懂了
- 基于Redis实现的分布式锁知识点总结
- 基于SSM实现的个人网盘系统源码
- 从Linux源码看Socket的listen及连接队列
- 大佬把Spring框架总结的「无比详细」,看完还说不懂别学了
- Spring Cloud微服务分布式物联网平台前后端分离源码
- 一口气看完45个寄存器,CPU核心技术大揭秘
- Python爬虫遇到验证码的几种处理方式,文章末尾有源码
- 运动|“长期化妆”和“长期素颜”,5年后皮肤有什么区别?看完你就懂
