认识Redis的跳跃表的结构


前言

这几天在读《Redis 设计与实现》,推荐大家阅读一下。加上也看了很多的博客,在这里总结一下关于Redis跳跃表的笔记
先把关于Redis跳跃表的重点总结一下在这里:

  1. 跳跃表是有序集合(zset)的底层实现之一
  2. redis的跳跃表实现由zskiplist和zskiplistNode两个结构组成,其中zskiplist用于保存跳跃表信息(比如表头节点,表尾节点,长度),而zskiplistNode则用于表示跳跃表节点
  3. 每个跳跃表节点的层高都是1至32之间的随机数
  4. 在同一个跳跃表中,多个节点可以包含相同的分值,但每个节点的成员对象必须是唯一的
  5. 跳跃表中的节点按照分值大小进行排序,当分值相同时,节点按照成员对象的大小进行排序

GitHub上也有源码–>Redis源码地址
关于跳跃表的位置在t_zset.c里面,对具体实现有兴趣的同学可以去研究一下


一、什么是跳跃表?

前面咱们介绍了单链表双链表,其实跳跃表也是一种链式的数据存储结构,具体是用一种类似于”索引”的思想,提取出链表中的部分关键节点。
如果是一个单链表的话,他查找数据的时间复杂度为O(n),咱么给单链表添加一级索引 每两个节点提取一个节点到上一级,我们把诌出来的哪一级叫做索引或者索引层,如下图:
在这里插入图片描述
我们要是查找值为6的节点,那么路线如下在这里插入图片描述
是不是要比我们从单链表一个一个查找的要快很多。
当然,既然已经提取出了一层关键节点作为索引,那么可以进一步提取索引,提出一层索引的索引。如下:
在这里插入图片描述
如果我们要查找值为6的节点,只需要经过1->5这个两个节点就找到了,是不是变得更快了。

跳跃表的层级极限:当同一层只有两个节点的时候, 就达到了跳跃表的层级极限,因为一个节点没有比较的意义

跳跃表是一种随机化的数据结构(通过抛硬币来决定层数)
当大量的新节点通过逐层比较,最终插入到原链表之后,上层的索引节点会渐渐变得不够用。这时候需要从新节点当中选取一部分提到上一层,可是究竟提拔谁,忽略谁?关于这一点,跳跃表的设计者采用了抛硬币的方式。
意思就是说随机决定新节点是否提拔,每次向上提拔一层的几率是50%。

那么为什么要用抛硬币?

  • 因为跳跃表删除和添加的节点是不可预测的,很难用一种有效的算法来保证跳表的索引部分始终均匀。
  • 随机抛硬币的方法虽然不能保证索引绝对均匀分布,却可以让大体趋于均匀

二、认识Redis的跳跃表的结构

Redis的跳跃表与我们普通的跳跃表区别相差很多

在这里插入图片描述
此图来源于《Redis的设计与实现》

在这里插入图片描述
使用跳跃表的优势:

  • 效率和红黑树以及avl树不相上下
  • 原理简单

Redis只在两个地方用到了跳跃表
1.实现有序集合键
2.在集群节点中作用内部数据结构


总结

1.跳跃表 VS 二叉查找树
二叉树的插入,删除,查找也是近似O(logn)的时间复杂度
不过,二叉查找树是有可能出现一种极端的情况,那就是如果插入的数据刚好有序,那么所有的节点会偏向某一边
这种结构会导致二叉查找树效率变为O(n),这会使二叉查找树大打折扣


2.跳跃表 VS 红黑树
红黑树比跳跃表复杂,学习成本偏高
而且红黑树插入,删除节点时,是通过调整结构来保持红黑树的平衡,比起跳跃表直接通过一个随机数来决定跨越几层,在时间复杂度的花销上是要高于跳跃表的。
也不是说红黑树比跳跃表差,在某些情况下,红黑树也是一种很好的选择,具体情况具体分析

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redis跳跃表(Skip List)是一种有序数据结构,用于实现有序集合(Sorted Set)数据类型。在Redis中,插入和更新操作都是基于跳跃表进行的。 对于插入操作,Redis使用跳跃表来维护有序集合。当需要将一个新的元素插入到有序集合中时,Redis首先会在跳跃表中寻找插入位置。通过跳跃表的索引层,Redis可以快速定位到需要插入的位置,而不必遍历整个有序集合。 具体的插入过程如下: 1. 生成一个随机层数level,决定要在跳跃表中插入的元素的索引层高度。 2. 从跳跃表的最高层开始,沿着索引层逐层下降,寻找插入位置,并记录每一层上离插入位置最近的节点。 3. 在底层插入新元素,并将该元素连接到每一层上离插入位置最近的节点。 4. 根据一定的概率,判断是否将新插入的元素提升为索引层的节点。 对于更新操作,Redis将其视为先删除旧元素,再插入新元素的操作。具体的更新过程如下: 1. 在跳跃表中搜索要更新的元素。 2. 如果找到了要更新的元素,从跳跃表中删除该元素。 3. 根据插入操作的方法,在跳跃表中插入新元素。 插入和更新操作都利用了跳跃表的特性,即通过索引层的建立,可以快速定位和搜索元素,从而提高插入和更新操作的效率。跳跃表的插入和更新操作时间复杂度都是O(log n),其中n是有序集合中元素的数量。因此,Redis利用跳跃表实现了高效的插入和更新功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值