三、redis数据存储之跳跃表(SKIP LIST)

导读

前面文章【一、深入理解redis之需要掌握的知识点 】中,我们对redis需要学习的内容框架进行了一个梳理。【二、redis中String和List两种数据类型和应用场景 】、【二、redis中Hash、Set、SortedSet应用场景 】两篇文章我们对redis中String、List、Hash、Set、SortedSet五种数据类型做了一下讲解,并且对他们各自的应用场景进行了介绍。

本篇文章我们将要深入学习支撑SortedSet排序背后的数据结构,跳跃表;

如果大家在工作、学习、面试中针对redis还有什么疑问或者其他问题,可以评论区告诉我。
为了保证可以连续不间断的获取最新的技术分析及讲解,建议关注本博客【不吃_花椒的博客】。

总图(下面有分解图)

在这里插入图片描述

解释

在这里插入图片描述
一、

在redis的SortedSet中使用双向链表存储数据,并按照权重(Score分值)进行排序,但是它用空间换时间的方式实现了跳跃表的概念。

二、

如果此时SET只是一个单纯的双向链表,那么当现在要新插入数据“A1-8”时候,他需要从双向链表的头部元素U开始,从左向右寻找,直到找到“W1-7”和“X1-10”之间然后插入。

此时他查找的时间复杂度是O(n),插入的时间复杂度为O(1)。之所以插入的时间复杂度为O(1)因为他只需要改变“W1-7”元素的next指针到“A1-8”,“A1-8”的next指针到“X1-10”。(注意:要理解这个操作需要先理解链表,请自行了解,链表的优缺点是:插入、删除快查找慢)

三、

在redis的SortedSet中使用了跳跃表逻辑的双向链表(注意去看跳跃双向链表的论文)。当此时要插入新数据“A1-8”时,他从双向链表的头部元素“U1-1”开始自上而下开始寻找。

他首先判断当前“A1-8”的值大于“U1-1”的值,因此应该向右侧看,因此开始自上而下的开始找他的跳跃索引;

当他找到“U3”时候,发现“U3”的右边都指向空;那么继续向下寻找找到“U2”,发现“U2”右侧指向“W2”,然后跳跃到“W2”节点;

此时用“W2”的根节点“W1-7”的值与“A1-8”进行比较发现还需要自己向右侧看;

此时再自上而下遍历“W1-7”的跳跃索引“W2”,发现“W2”右侧节点指向“Y2”,然后跳跃到“Y2”节点;

此时用“Y2”的根节点“Y1-12”的值与“A1-8”进行比较,发现需要向左侧看,因此跳跃到“X1-10”节点;

然后再用“X1-10”的值与“A1-8”的值进行比较,发现需要继续向左看,然后跳跃到“W1-7”节点:然后再进行比较发现“A1-8”的值大于“W1-7”的值,所以把“A1-8”插入到“W1-7”与“X1-10”之间。

四、

当跳跃链表要插入的新数据“A1-8”找到要插入的位置并插入到“W1-7”和“X1-10”之间后,他开始用投硬币的方式构建自己的跳跃索引。

如果此时他投硬币的结果为0,那么直接结束构建跳跃索引的过程;

如果此时他投硬币的结果为1,那么他创建一个自己的跳跃索引“A2”,并通过递归查找“A1-8”的左侧和右侧,直到找到有2层跳跃索引的元素“W1-7”和“Y1-12”,并把“A1-8”的跳跃索引“A2”插入到“W1-7”和“Y1-12”的各自的2层跳跃索引“W2”和“Y2”中间,此时“A1-8”的2层跳跃索引“A2”构建完毕;

此时继续通过投硬币的方式判断是否继续构建3层索引,如果投硬币的结果为0则直接结束构建跳跃索引,如果投硬币的结果为1,那么继续构建“A1-8”的第三层索引“A3”;

如此循环往复,构建第4层,第5层跳跃索引,直到投硬币结果为0而结束跳跃索引的构建;

五、

注意:当构建每层次跳跃索引时,它只会寻找具备相同层次的跳跃索引的元素。例如:如果“A1-8”要构建他的第三层跳跃索引“A3”,那么他向左向右递归时候,最终“A3”的右侧指向空,“A3”的左侧指向同样具备第三层跳跃索引的元素“U1-1”的跳跃索引“U3”。

图示

在这里插入图片描述

往期文章

Redis

一、深入理解redis之需要掌握的知识点

二、redis中String和List两种数据类型和应用场景

二、redis中基础数据类型Hash、Set、SortedSet及其应用场景

Java集合

一、深入理解-Java集合初篇

二、Jdk1.7和1.8中HashMap数据结构及源码分析

三、JDK1.7和1.8HashMap数据结构及源码分析-续

四、深入理解Java中的HashMap「网易面试快答」

五、深入理解JDK1.7中HashMap哈希冲突解决方案

六、深入理解JDK1.8中HashMap哈希冲突解决方案

七、JDK1.7中HashMap扩容机制

八、JDK1.8中HashMap扩容机制
Java-IO体系

一、C10K问题经典问答
二、java.nio.ByteBuffer用法小结
三、Channel 通道
四、Selector选择器
五、Centos-Linux安装nc
六、windows环境下netcat的安装及使用
七、IDEA的maven项目的netty包的导入(其他jar同)
八、JAVA IO/NIO
九、网络IO原理-创建ServerSocket的过程
十、网络IO原理-彻底弄懂IO
十一、JAVA中ServerSocket调用Linux系统内核
十二、IO进化过程之BIO
十三、Java-IO进化过程之NIO
十四、使用Selector(多路复用器)实现Netty中Reactor单线程模型
十五、使用Selector(多路复用器)实现Netty中Reactor主从模型
十六、Netty入门服务端代码
十七、IO进化过程之EVENT(EPOLL-事件驱动异步模型)

如需了解更多更详细内容也可关注本人CSDN博客:不吃_花椒