Redis Zset的底层秘密:跳表(Skip List)的精妙设计 - 详解

news/2025/10/4 22:27:14/文章来源:https://www.cnblogs.com/slgkaifa/p/19126016

Redis Zset的底层秘密:跳表(Skip List)的精妙设计 - 详解

在Redis众多数据结构中,有序集合(Zset)是一个非常强大的工具,它不仅支持集合的唯一性,还能根据分数进行自动排序。当我们使用zaddzrangezrank等命令时,背后正是一个高效的数据结构在支撑——跳表(Skip List)。今天,我们就来深入探索Redis中Zset的底层实现,重点剖析跳表这一精妙的数据结构。

什么是跳表?

跳表是一种基于链表的数据结构,它通过在链表中添加多级索引,实现快速的查找、插入和删除操作。想象一下,普通的链表查找需要O(n)的时间复杂度,而跳表则通过在不同层级上"跳跃",将时间复杂度降低到O(log n)。

跳表的核心思想是:在链表的基础上,构建多级索引。每一级索引都包含当前层级的节点,通过这些索引,我们可以快速跳过大量节点,直接定位到目标区域。

跳表的结构

Redis中的跳表实现非常精巧,它由zskiplistNode结构体组成:

typedef struct zskiplistNode {sds ele;                // 成员字符串double score;           // 分数值struct zskiplistLevel {struct zskiplistNode *forward; // 指向下一节点unsigned int span;          // 跨越节点数} level[];                  // 动态数组,表示不同层级的连接
} zskiplistNode;

每个节点包含:

  • ele:成员字符串
  • score:分数值
  • level[]:动态数组,表示该节点在不同层级的连接

跳表还包含一个zskiplist结构体,用于管理整个跳表:

typedef struct zskiplist {struct zskiplistNode *header, *tail;unsigned long length;int level;
} zskiplist;

跳表的工作原理

查找操作

跳表的查找过程类似于二分查找:

  1. 从最高层开始
  2. 比较当前节点的分数
  3. 如果当前节点的分数小于目标分数,则继续向后查找
  4. 如果当前节点的分数大于目标分数,则向下一层
  5. 重复直到找到目标节点或到达最低层
zskiplistNode *zslGetNode(zskiplist *zsl, double score, sds ele) {zskiplistNode *x = zsl->header;for (int i = zsl->level-1; i >= 0; i--) {while (x->level[i].forward &&x->level[i].forward->score < score) {x = x->level[i].forward;}}x = x->level[0].forward;if (x && score == x->score && sdslen(ele) == sdslen(x->ele) &&memcmp(ele, x->ele, sdslen(ele)) == 0) {return x;}return NULL;
}

插入操作

插入操作包含两个关键步骤:

  1. 查找插入位置
  2. 创建新节点并更新索引

Redis使用概率算法决定新节点的层数,确保较高的层数较少,平衡空间和效率:

int zslRandomLevel() {int level = 1;while ((random() & 0xFFFF) < ZSKIPLIST_P * 0xFFFF)level += 1;return (level < ZSKIPLIST_MAXLEVEL) ? level : ZSKIPLIST_MAXLEVEL;
}

删除操作

删除操作与插入类似,先找到节点,然后从所有层级中移除该节点。

为什么Redis选择跳表而非红黑树或B+树?

Redis的作者Salvatore Sanfilippo曾明确表示:“跳跃表更易于实现、调试和扩展”。这背后有多个原因:

1. 实现简单

跳表的代码实现比红黑树简单得多。红黑树需要处理复杂的旋转、颜色标记和平衡操作,而跳表只需要简单的指针操作。

2. 内存效率

在Redis的内存环境中,跳表的平均每个元素占用64字节,而红黑树平均需要72字节(包含父指针和颜色标记)。对于内存敏感的Redis来说,这是重要的优势。

3. 缓存友好

跳表的连续内存访问模式比红黑树的指针跳转更缓存友好,现代CPU架构下性能更优。

4. 区间查询效率

跳表在区间查询时效率更高。它可以在O(log n)时间内定位到区间的起点,然后在原始链表中线性遍历,而红黑树需要遍历所有节点。

5. 并发友好

跳表在并发环境下可以通过改变索引构建策略,有效平衡执行效率和内存消耗。红黑树的平衡依赖于复杂的旋转操作。

跳表与哈希表的结合

Redis的Zset不仅使用跳表,还配合哈希表一起工作:

这种设计使得Zset既能高效进行范围查询(通过跳表),又能高效进行单点查询(通过哈希表)。

何时使用压缩列表?

Redis在Zset元素数量较少时,会使用压缩列表(ziplist)来节省内存:

  • 元素个数 ≤ 128
  • 每个元素的成员名和分数长度 ≤ 64字节

当不满足上述条件时,Redis会切换到跳表+哈希表的实现。

实际应用:Redis Zset的高效性能

在实际应用中,跳表的特性使Redis Zset在以下场景表现出色:

  1. 排行榜系统:快速获取前N名或特定分数范围内的成员
  2. 带优先级的任务队列:根据优先级排序任务
  3. 实时分析:按分数范围查询统计

例如,一个热门游戏的排行榜系统,使用Zset可以轻松实现:

# 添加玩家分数
ZADD leaderboard 1000 "player1"
ZADD leaderboard 1500 "player2"
# 获取前3名
ZRANGE leaderboard 0 2 WITHSCORES

总结

跳表是Redis Zset底层实现的核心数据结构,它的设计体现了Redis作者对简单性、效率和实用性的追求。通过多级索引,跳表在O(log n)的时间复杂度下实现了快速的查找、插入和删除操作,同时保持了实现的简洁性。

Redis的Zset之所以能成为如此强大的数据结构,正是因为它巧妙地结合了跳表的有序性和哈希表的快速查找能力。这种设计不仅满足了Redis对高性能的要求,还保持了代码的简洁和可维护性。

在Redis的世界里,跳表就像一位默默工作的"幕后英雄",以优雅而高效的方式支撑着无数应用的有序集合需求。理解跳表的工作原理,不仅能帮助我们更好地使用Redis,也能让我们欣赏到数据结构设计的精妙之处。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/927622.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网站开发部职责搜款网站一起做网店

我们通过将近半天的搜索数据&#xff0c;查到了美国五大湖中优势物种的食物网数据&#xff0c;以Eric伊利湖为例&#xff0c;共包含34各优势物种&#xff0c;相互之间的关系如下图所示&#xff1a; 一、题目 &#xff08;一&#xff09; 赛题原文 2024 MCM Problem A: Reso…

实用指南:TCP连接关闭的“礼貌告别“与“果断离场“:深入解析Linger选项

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

郑州做网站和推广哪家好wordpress 顶部栏

文章目录 ISO文件格式光盘的基本概念光盘种类特点DVDR光盘使用windows调用Linux调用Linux平台下用到的C库:读取设备驱动列表向光驱中写文件 数字存储媒体快速发展的今天&#xff0c;光驱的使用已经不像以前那样普及了。但是在数据备份、安装软件和操作系统、旧设备兼容等领域还…

虚拟商品购物网站源码网站设计参考网址

Nginx是一个高性能的web服务器和反向代理服务器&#xff0c;用于HTTP、HTTPS、SMTP、POP3和IMAP协议。因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。 &#xff08;1&#xff09;更快 这表现在两个方面&#xff1a;一方面&#xff0c;在正常情况下&…

网站的字体做多大企业管理咨询类公司

本文实例讲述了Laravel5.1数据库连接、创建数据库、创建model及创建控制器的方法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;前言&#xff1a;laravel创建数据库&#xff0c;实际可以手动创建&#xff0c;如古老的phpmyadmin 等均可以。一、数据库连接&#xff1a…

深入解析:从 CefSharp 迁移至 DotNetBrowser

深入解析:从 CefSharp 迁移至 DotNetBrowser2025-10-04 22:18 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: b…

为什么很多地级市、县级市都把高铁站盖到了郊区呢 —— 以鞍山西站、海城西站为例

为什么很多地级市、县级市都把高铁站盖到了郊区呢 —— 以鞍山西站、海城西站为例每次假期都是要从高铁西站下车,每每如此总是免不得抱怨,毕竟这个郊区的西站无形之中就把回家的距离拉远了快30公里,如果短途做高铁,…

AtCoder Beginner Contest 426 实况记录 + A-D 题解

省流:只有 \(1000\) 分,遗憾离场。 这篇文章用来警示大家不要在比赛中犯相同的错误。 A. OS Versions AI 出来解释一下 \(\texttt{newer than}\) 翻译成“更新”何意味?请判断版本 \(X\) 与版本 \(Y\) 是否相同或更…

提示词攻击如何防范(2025):从 Indirect Prompt Injection 到 RAG 供应链的分层防御实战

2025 年 LLM 首要风险仍是 Prompt Injection / 间接提示词注入(Indirect Prompt Injection, IPI),RAG 供应链与外部工具风险 针对主要AI应用的暴露面。 需要对齐OWASP LLM01 / MITRE ATLAS / NIST AI RMF,并提供 *…

但行好事,莫问前程

但行好事,莫问前程又是一次忘了在第一天前写的考试。 这一个月经历了太多的跌宕起伏:从上一次考试的惊喜,到渐渐出现问题,再到逐渐回归正常的学习,最后在第二次考试之前又出现了大问题。具体问题是什么不好说。 我…

【STM32项目开源】基于STM32的智能养殖场环境监测系统 - 详解

【STM32项目开源】基于STM32的智能养殖场环境监测系统 - 详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Cons…

wordpress地址为灰色免费智能seo收录工具

集成联调交付&#xff08;Integrated Joint Debugging and Delivery&#xff09;是软件开发过程中的一个阶段&#xff0c;主要涉及将不同的软件模块或组件整合在一起&#xff0c;并进行联合调试和测试&#xff0c;以确保它们能够作为一个整体正常工作。这个过程通常发生在开发周…

前端学习教程-Axios

Axios 是一个基于 Promise 的流行的 HTTP 客户端,用于浏览器和 Node.js 环境,支持 Promise API、拦截请求和响应、转换请求数据和响应数据等功能。 一、安装 Axios使用 npm 或 yarn 安装(适用于 Vue/React 等项目)…

镇江网站开发图片摄影网站

在2018杭州云栖大会的主论坛上&#xff0c;阿里云技术研发总经理蒋江伟发表了《飞天2.0&#xff0c;万物智能的基础服务》的主题演讲&#xff0c;从全连接、安全、简便、高速四个方面&#xff0c;阐述了飞天2.0网络的新特性。 蒋江伟表示&#xff0c;万物智能时代产生的海量数据…

网站域名怎么做杰恩设计网站是谁做的

JVM 案例 案例一&#xff1a;服务器内存不足&#xff0c;影响Java应用 问题&#xff1a; 收到报警&#xff0c;某Java应用集群中一台服务器可用内存不足&#xff0c;超过报警阈值。 排查过程&#xff1a; 首先&#xff0c;通过Hickwall查看该应用各项指标&#xff0c;发现无论…

网站是怎样制作的自媒体135手机版

电商技术揭秘相关系列文章 电商技术揭秘一&#xff1a;电商架构设计与核心技术 电商技术揭秘二&#xff1a;电商平台推荐系统的实现与优化 电商技术揭秘三&#xff1a;电商平台的支付与结算系统 电商技术揭秘四&#xff1a;电商平台的物流管理系统 电商技术揭秘五&#xf…

网站开发分包网站开发运营工程师待遇

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《C》 《Linux》 《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 一、默认成员函数二、构造函数构造函数的概念及特性 三、析构函数析构函数的特性…

网站如何交换链接临淄房产信息网123

文章目录 一、区别二、编写loader三、编写plugin参考文献 一、区别 前面两节我们有提到Loader与Plugin对应的概念&#xff0c;先来回顾下 loader 是文件加载器&#xff0c;能够加载资源文件&#xff0c;并对这些文件进行一些处理&#xff0c;诸如编译、压缩等&#xff0c;最终…

『回忆录』返校前夜 230102

经典佳作返校,一件每个周末都会经历的事情。而对于居家学习的我们,成了一个梦。 而这个梦,如今已变成现实。一个再平常不过的周末,我们上着竞赛。可是,中午wsh就把我们所有人叫到教室。 “因为疫情,学校要求你们…

断更

今天很忙,没时间学习