Redis 跳表(skiplist)知识点详解

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: Redis框架从入门到学精(全)Python操作Redis从入门到精通附代码(全)Redis的常见面试题(全)一文读懂基于Redis的Amazon MemoryDB数据库科普下Redis数据类型中底层的数据结构(常考点)数据类型可以存储的值操作应用场景string字符串、整数或者浮点对整个字符串或者字符串的其中一部分执行操作,对整数和浮点数执行自增或者自减操作做简单的键值对缓存,计数器,共享session以及限速list列表。

前言

关于Redis的相关知识点可看我之前的文章:

  1. Redis框架从入门到学精(全)
  2. Python操作Redis从入门到精通附代码(全)
  3. Redis的常见面试题(全)
  4. 一文读懂基于Redis的Amazon MemoryDB数据库

科普下Redis数据类型中底层的数据结构(常考点)

数据类型 可以存储的值 操作 应用场景
string 字符串、整数或者浮点 对整个字符串或者字符串的其中一部分执行操作,对整数和浮点数执行自增或者自减操作 做简单的键值对缓存,计数器,共享session以及限速
list 列表 从两端压入或者弹出元素,对单个或者多个元素进行修剪,只保留一个范围内的元素 存储一些列表型的数据结构,类似粉丝列表、文章的评论列表之类的
set 无序集合 添加、获取、移除单个元素,检查一个元素是否存在于集合中。计算交集、并集、差集。从集合里面随机获取元素 交集、并集、差集的操作,比如交集,可以把两个人的粉丝列表整一,或者是用户的喜好标签等
hash 包含键值对的无序散列 添加、获取、移除单个键值对。获取所有键值对。检查某个键是否存在 结构化的数据,比如一个对象
zset 有序集合 添加、获取、删除元素。根据分值范围或者成员来获取元素。计算一个键的排名。 去重但可以排序,如获取排名前几名的用户,排行榜等

1. zset底层结构

zset主要是有序集合

底层结构有压缩列表和跳表两种结构

数据结构 描述 优点 缺点 应用场景
压缩列表 在列表的前面加入了列表长度、尾部偏移量、列表元素个数,在列表的后面加入了列表结束标识 有利于快速的找到首尾节点 不利于找其他的元素,只能一个个遍历 1.有序集合保存的元素数量小于128个
2.有序集合保存的所有元素长度小于64字节
跳表 在链表的基础上增加了多级索引,通过多级索引位置的转跳,实现快速查找元素 可快速查找对应元素,用空间换实践,实践复杂度笑了 元素数量比较多 或者 元素比较长的字符串

2. 跳表结构

之所以有跳表这个结构是为了解决平衡二叉树复杂问题

hash可快速定位,但是不是有序
若用二叉查找树,有序的话会退化为链表
链表加平衡因子,变成平衡二叉树(可分为b树、b+树、红黑树等)

跳表和平衡二叉树的区别如下:

共同点 差异
查找、插入、删除的时间复杂度都是o(logn) 跳表 查找区间元素比较快,但是 平衡二叉树 查找区间元素 一开始需要定位左端点,之后查找后续节点比较费时

最后选用了跳表,是因为跳表实现起来容易,所以用它来实现有序集合

基本的性质:

  1. 主要是单链表 + 索引的方式实现,以空间换时间的形式,提高查找速度
  2. 底层主要由两个结构组成

在这里插入图片描述

  • zskiplist:保存跳表信息(头尾节点、跳表层数最大的层数、长度)
  • zkiplistnode:保存跳表节点信息(比如level层:每层都有两个属性,指针和跨度,跨度大距离远)

类似如下结构,原本是1到6的链表结构,专门找5这个数字的话,需要遍历5个节点
如果每隔一个数字建立一个索引,具体如下:
在这里插入图片描述

通过一级索引来减少遍历节点的次数
如果觉得一级索引比较慢,可以在一级索引的基础上在建立索引

当数据量比较大的时候,跳表查询、插入、删除的复杂度均为为 O(logn),本身的主要思想是二分法

3. 拓展思考

为什么zset使用跳表而不用红黑树或者二叉树?

Redis直接操作内存而不是磁盘,所以不需读取IO,速度比较快

  • 跳表不是很占用内存(基本取决于节点数据),本身节点的数据参数会让内存密集度小于B+树
  • 跳表本身实现方式比其他结构都要简单(将相同级别的节点存储在同一个文件或者映射中,有利于解决缓存局部性问题)

而MYSQL使用B+树是为了减少IO以及支持范围查询

关于这个问题的讲解,结合MYSQL的底层结构讲解比较清晰。
(对应的数据库最终使用了b+树,可看我这篇文章的推理:Mysql底层原理详细剖析+常见面试题(全)

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
2月前
|
运维 NoSQL 测试技术
从一个事故中理解Redis(几乎)所有知识点
作者从一个事故中总结了Redis(几乎)所有的知识点,供大家学习。
105 12
|
6月前
|
存储 NoSQL Redis
Redis系列学习文章分享---第十六篇(Redis原理1篇--Redis数据结构-动态字符串,insert,Dict,ZipList,QuickList,SkipList,RedisObject)
Redis系列学习文章分享---第十六篇(Redis原理1篇--Redis数据结构-动态字符串,insert,Dict,ZipList,QuickList,SkipList,RedisObject)
85 1
|
1月前
|
存储 NoSQL Redis
Redis常见面试题:ZSet底层数据结构,SDS、压缩列表ZipList、跳表SkipList
String类型底层数据结构,List类型全面解析,ZSet底层数据结构;简单动态字符串SDS、压缩列表ZipList、哈希表、跳表SkipList、整数数组IntSet
|
5月前
|
消息中间件 存储 NoSQL
Redis数据结构—跳跃表 skiplist 实现源码分析
Redis 是一个内存中的数据结构服务器,使用跳跃表(skiplist)来实现有序集合。跳跃表是一种概率型数据结构,支持平均 O(logN) 查找复杂度,它通过多层链表加速查找,同时保持有序性。节点高度随机生成,最大为 32 层,以平衡查找速度和空间效率。跳跃表在 Redis 中用于插入、删除和按范围查询元素,其内部节点包含对象、分值、后退指针和多个前向指针。Redis 源码中的 `t_zset.c` 文件包含了跳跃表的具体实现细节。
|
5月前
|
存储 NoSQL Redis
Redis数据结构—跳跃表 skiplist
Redis数据结构—跳跃表 skiplist
|
7月前
|
缓存 NoSQL 定位技术
深入探索Redis:面试中必须掌握的关键知识点
深入探索Redis:面试中必须掌握的关键知识点
|
7月前
|
存储 NoSQL Redis
Redis入门到通关之数据结构解析-SkipList
Redis入门到通关之数据结构解析-SkipList
90 0
|
7月前
|
NoSQL 算法 Redis
redis7.0源码阅读(五):跳表(skiplist)
redis7.0源码阅读(五):跳表(skiplist)
305 1
|
7月前
|
NoSQL Redis C++
Redis跳表
Redis跳表
67 0
|
7月前
|
NoSQL Go API
Golang实现redis系列-(4)实现跳表容器
Golang实现redis系列-(4)实现跳表容器
42 0