Redis跳跃表(SkipList)
什么是跳跃表
跳跃表(skiplist)是一种有序且随机化的数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。
跳跃表的用处
有序集合(zset)的底层可以采用数组、链表、平衡树等结果来实现, 但是他们都有各自的缺点,数组方便查询,但不便于插入和删除;链表方便插入和删除,但是不利于查找;平衡树/红黑树效率高但是实现起来很复杂。
为什么 Redis 不使用这样一些结构呢?
- 性能考虑: 在高并发的情况下,树形结构需要执行一些类似于 rebalance 这样的可能涉及整棵树的操作,相对来说跳跃表的变化只涉及局部
- 实现考虑: 在复杂度与红黑树相同的情况下,跳跃表实现起来更简单,看起来也更加直观
所以Redis自己实现了跳跃表来来当做有序集合(zset)的底层实现, 他的查询复杂度平均O(logN), 最坏O(N), 堪比红黑树,但实现起来远比红黑树简单。
跳跃表解决什么问题
先分析一下链表,链表的优势是插入、删除快,查询很慢。对于链表来讲,即便链表中存储的数据是有序的,如果我们要向在其中查找某个数据,它只能从头到尾遍历链表。这样查找效率就会很低,时间复杂度会很高,达到了O(n)。
若要查找值为5的元素,需要从第一个元素依次向后查询,共需比较5次才可以。
假设要查找值为5的元素,可以先在索引层遍历,当遍历到索引层中值为5的元素时就返回。在原单链表中查找值为5的元素,需要遍历比较5次才可以。而现在有了一级索引后,只需要遍历3次就可以找到对应的元素。
从上个例子中,每加来一层索引后,查找元素需要遍历的次数就会减少,查询效率也得到提升,同理在一级索引的基础上,在加二级索引。
假设要查找值为6的元素,可以先在索引层遍历,当遍历到索引层中值为7的元素时,则会下降到下层链表层继续查找值为6的元素。
从图中我们可以看出,查找效率又有了提升,因为在这里例子中我们的数据量很少,当有大量的数据时,我们可以增加多级索引,在查询时,效率可以得到明显的提升。像这种链表增加多种索引的结构,就是 跳跃表。
跳跃表是如何进行查找的呢?
- 优先从高层查找
- 若当前节点的值小于要查找的值,且 next 指针指向大于目标值的节点就降一级寻找,或 next 指针指向了 null ,也需要降一级查找。
与 B+树 对比
B+树存储就是一个平衡搜索树,如果要插入一个节点那么就检索到这个节点插入,插入的时候要维护子树的规则(平衡搜索树)还有就是 B+树 在 mysql 当中还要在一定的情况下扩容和缩容。这就要消耗一定的资源算力,而跳表这里用随机层数来解决这个问题,这样就解决了插入的消耗问题,比平衡术更加优秀。
由此可见跳表的本质是解决查找问题。
插入元素实现
如果理解上面所说的跳跃表的原理,那么很容易理清楚插入节点时发生的几个动作 (几乎跟链表类似):
- 找到当前我需要插入的位置
- 创建新节点,调整前后的指针指向,完成插入
跳表的增删改
插入操作
插入操作在实现起来是最麻烦的,需要的考虑的东西最多。插入需要考虑是否插入索引,插入几层等问题。其流程为:
- 首先通过上面查找的方式,找到要插入的节点
- 插入完这一层,需要考虑上一层是否插入,首先判断当前索引层级,如果大于最大值那么就停止(说明已经到最高索引层)。否则就使用随机化的方法去判断是否向上层插入索引,即产生一个[0-1]的随机数。如果小于0.5就向上插入索引,插入完毕后再次使用随机数判断是否向上插入索引
- 继续上的操作,直到概率退出或者索引层数大于最大索引层
删除操作
删除操作比起查询稍微复杂一丢丢,但是比插入简单。删除需要改变链表结构,需要先找到元素,然后对于每个层的相关节点重排前向后向指针,所以需要处理好节点之间的联系,同时还要更新层数。
对于删除操作你需要谨记以下几点:
- 删除当前节点和这个节点的前后节点都有关系
- 删除当前层节点之后,下一层该key的节点也要删除,一直删除到最底层
更新操作
暂时没做研究
总结
- 跳跃表基于单链表+索引的方式实现
- 跳跃表是以空间换时间的方式提升了查找速度
- Redis的跳跃表实现由 zskiplist 和 zskiplistnode 两个结构组成,其中 zskiplist 用于保存跳跃表信息(比如表头节点、表尾节点、长度),而 zskiplistnode 则用于表示跳跃表节点
Redis跳跃表(SkipList)相关推荐
- Redis中ZSet的底层数据结构跳跃表skiplist,你真的了解吗?
欢迎大家关注我的微信公众号[老周聊架构],Java后端主流技术栈的原理.源码分析.架构以及各种互联网高并发.高性能.高可用的解决方案. 一.前言 老周写这篇文章的初衷是这样的,之前项目中有大量使用 R ...
- Redis 为什么这么快? Redis 的有序集合 zset 的底层实现原理是什么? —— 跳跃表 skiplist
Redis有序集合 zset 的底层实现--跳跃表skiplist Redis简介 Redis是一个开源的内存中的数据结构存储系统,它可以用作:数据库.缓存和消息中间件. 它支持多种类型的数据结构,如 ...
- Redis跳跃表详解
1.前言 自己学跳跃表是因为当初听人说想要找一份高薪工作, Redis跳跃表是要知道的. 当时学的时候也是网上的文章反复看, 花了几个晚上才彻底弄明白, 所以在此记录一下吧, 为了下次面试好回顾 ...
- 跳跃表 skipList 跳表的原理以及golang实现
跳跃表 skipList 调表的原理以及golang实现 调表skiplist 是一个特殊的链表,相比一般的链表有更高的查找效率,跳跃表的查找,插入,删除的时间复杂度O(logN) Redis中的有序 ...
- Redis 跳跃表原理
跳跃表 跳跃表 (skiplist) 是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针从而达到快速访问节点的目的. 跳跃表是 redis 有序集合 zset 的底层实现方式之一.(当元 ...
- Redis - 跳跃表
一.跳跃表简介 跳跃表(skiplist)是一种随机化的数据结构,由 William Pugh 在论文<Skip lists: a probabilistic alternative to ba ...
- Redis面试题-Redis跳跃表
本文参考 嗨客网 Redis面试题 Redis跳跃表 什么是跳跃表 Redis 中的跳跃表是一种有序的数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的. 为什么使用跳 ...
- redis跳跃表与二分查找
一 前言 本篇内容主要是讲解redis跳跃表的基础概念,科普一下读者知道有这种随机数据结构的概念,. 公众号:知识追寻者 知识追寻者(Inheriting the spirit of open sou ...
- redis跳跃表图解插入详述
最近跟着黄健宏老师的<redis设计与实现>学习redis数据结构,看到跳跃表一节时,发现只有两节: 如此简略,应该是很简单吧,嘿嘿,抱着这种想法,我打开了redis源码,查看了下跳跃表的 ...
最新文章
- net-speeder 安装
- UnicodeDecodeError: 'gbk' codec can't decode byte 0xab in position 43: illegal multibyte sequence
- 爱吃苹果的与喜欢篮球的没必要非得达成一致~
- Android onSaveInstanceState、onRestoreInstanceState保存数据
- JSF:在正确的阶段进行验证(了解生命周期)
- win11适合玩游戏吗 Windows11打游戏怎么样
- python列表内元素求和_Python之list对应元素求和
- 在Unity中使用.Net Remoting实现双向通信
- 安卓手机上虚拟linux系统教程,如何在安卓手机上安装Linux系统
- IE 浏览器 安装证书 无响应 卡死
- BZOJ3505 [Cqoi2014]数三角形
- power bi条件格式_Power BI中的条件格式
- 【vn.py】SpreadTrading价差交易
- git公钥私钥及密码说明
- 上级目录,同级目录简写【../,./】
- 鸿蒙5G多少钱一部手机,5G+鸿蒙,就是我下一部手机的标配,不接受反驳
- Java--网络编程(利用TCP实现简单的双人聊天)
- bootrom的类型
- VBA word 常用代码及注释
- I - The old Padawan Gym - 100285I——二分查找
热门文章
- PowerDVD(了解收藏)
- 测试sony电视屏的软件,Mirror for Sony TV 3.6.2 for Mac 索尼电视屏幕镜像工具
- 雨林木风linux如何安装教程,雨林木风桌面操作系统Ylmf OS 4.0安装演示
- 2017全国计算机ps版本,Adobe Photoshop v18.0.0 (PS CC 2017) 中文多语言版本 不断更新
- 3D建模怎么学,3D游戏建模怎么学
- 脸部动作编码系统(FACS)应用
- 查看linux网速的命令,Ubuntu中查看网速的命令
- Python脚本实现汉子转拼音
- 程序员出售上亿条个人信息被刑拘
- 【虚幻引擎UE】UE4/UE5 新人科普向