为什么 Redis 的有序集合(Sorted Set)要用跳表(Skip List)实现?深入解析设计哲学与实战对比

视频看了几百小时还迷糊?关注我,几分钟让你秒懂!

在 Redis 中,有序集合(Sorted Set / ZSet)是一个极其重要的数据结构,广泛用于排行榜、延迟任务、带权重的队列等场景。但你有没有想过:为什么 Redis 不用更“经典”的平衡树(如红黑树),而是选择相对冷门的跳表(Skip List)来实现 ZSet?

很多人第一反应是:“跳表性能好?”
——这没错,但只说对了一半。

真正的原因,是Redis 在性能、内存、代码复杂度和并发扩展性之间做出的精妙权衡。本文将从原理、源码、实战三个维度,彻底讲清楚这个问题,并附上Java + Spring Boot 对比案例,让你不仅知其然,更知其所以然。


一、ZSet 的核心需求是什么?

在设计 ZSet 底层结构前,Redis 团队首先明确了它的核心操作需求

操作时间复杂度要求说明
插入元素(ZADD)O(log N)需要按 score 排序
删除元素(ZREM)O(log N)快速定位并删除
范围查询(ZRANGE)O(log N + M)M 是返回元素个数
按分值范围查询(ZRANGEBYSCORE)O(log N + M)如查 80~100 分的用户
获取排名(ZRANK)O(log N)元素在有序序列中的位置

关键点:不仅要支持快速插入/删除,还要高效支持范围遍历


二、为什么不选红黑树(Red-Black Tree)?

红黑树是 C++ STLstd::map、JavaTreeMap的底层实现,具备 O(log N) 的增删改查能力。那为什么 Redis 不用它?

❌ 红黑树的致命缺陷:不擅长范围查询!

  • 红黑树是二叉搜索树,虽然中序遍历可得有序序列,但遍历时需要递归或栈模拟,无法像链表那样“一路 next”。
  • 要获取[score1, score2]区间内的所有元素,必须:
    1. 找到第一个 ≥ score1 的节点(O(log N))
    2. 从中序遍历开始,逐个访问后续节点,直到 > score2
  • 问题:中序遍历不是“线性指针跳转”,实现复杂,且缓存局部性差(节点分散在堆内存)。

📌结论:红黑树适合“单点查询”,但不适合 Redis 这种高频范围扫描的场景。


三、跳表(Skip List)的三大优势

跳表由 William Pugh 在 1989 年提出,是一种基于概率的多层链表结构。它完美契合 Redis 的需求。

✅ 优势 1:天然支持高效范围查询

跳表的底层是一条有序双向链表(Redis 实际用的是双向链表 + 层级指针),这意味着:

  • 一旦定位到起始节点,后续元素可通过next指针线性遍历,缓存友好。
  • ZRANGEZRANGEBYSCORE等命令实现极其简单高效。
// Redis 跳表节点定义(简化版) typedef struct zskiplistNode { sds ele; // 元素值(字符串) double score; // 分值 struct zskiplistNode *backward; // 后退指针(用于反向遍历) struct zskiplistLevel { struct zskiplistNode *forward; // 前进指针 unsigned long span; // 跨度(用于快速计算排名) } level[]; // 柔性数组,层级动态 } zskiplistNode;

🔍 注意:backward指针让跳表支持O(1) 反向遍历(如ZREVRANGE),这是普通跳表没有的优化!


✅ 优势 2:实现简单,代码可读性强

  • 红黑树:插入/删除需处理5 种旋转 + 颜色翻转,代码复杂,易出错。
  • 跳表:插入只需随机决定层数 + 更新指针,逻辑清晰。

Redis 作者Salvatore Sanfilippo(antirez)曾公开表示:

“跳表的代码比红黑树少得多,更容易调试和维护。”

对于一个单线程、追求稳定的系统来说,简单即可靠


✅ 优势 3:天然支持并发扩展(未来兼容性)

虽然 Redis 主线程是单线程,但跳表在并发场景下更容易加锁优化

  • 可对不同层级或区间加细粒度锁。
  • 而红黑树的旋转操作涉及多个节点,锁粒度难控制。

💡 虽然 Redis 目前没用多线程处理命令,但设计时已考虑未来可能性。


四、跳表 vs 其他结构:Redis 的完整选择逻辑

Redis 对 ZSet 的实现其实是混合策略

元素数量 & 大小底层结构原因
≤ 128 个元素,且每个成员 ≤ 64 字节ziplist(压缩列表)内存紧凑,连续存储,缓存友好
超出上述阈值skiplist + hashtable跳表负责排序,哈希表负责 O(1) 查找成员是否存在

📌双结构协同

  • 跳表:按 score 排序,支持范围查询。
  • 哈希表:通过 member 快速判断是否已存在(避免重复插入)。

五、Spring Boot 实战:排行榜场景对比

✅ 正确使用 ZSet(跳表优势体现)

@RestController public class LeaderboardController { @Autowired private StringRedisTemplate redisTemplate; // 更新玩家分数 public void updateScore(String playerId, double score) { redisTemplate.opsForZSet().add("game:leaderboard", playerId, score); } // 获取 Top 10(高效!O(logN + 10)) public Set<String> getTop10() { return redisTemplate.opsForZSet() .reverseRange("game:leaderboard", 0, 9); // 自动利用跳表有序性 } // 获取分数在 80~100 之间的玩家(范围查询) public Set<String> getPlayersByScore(double min, double max) { return redisTemplate.opsForZSet() .rangeByScore("game:leaderboard", min, max); } }

📌性能:即使有 100 万玩家,getTop10()依然毫秒级响应。


❌ 反例:用 TreeMap 模拟 ZSet(自造轮子)

// 错误:在 Java 内存中维护排行榜(无法分布式,内存爆炸) private final TreeMap<Double, Set<String>> leaderboard = new TreeMap<>(); public void addPlayer(String playerId, double score) { leaderboard.computeIfAbsent(score, k -> new HashSet<>()).add(playerId); } // 获取 Top 10:需要遍历整个 TreeMap! public List<String> getTop10Manual() { return leaderboard.descendingMap().values().stream() .flatMap(Set::stream) .limit(10) .collect(Collectors.toList()); }

⚠️问题

  • 无法跨服务共享
  • 内存占用大
  • 范围查询效率低(需遍历)

六、常见误区澄清

❓ 误区 1:“跳表性能不如红黑树?”

  • 事实:在平均情况下,跳表的查找/插入/删除复杂度也是O(log N),常数因子略大,但范围查询远胜红黑树
  • Redis 官方测试表明:跳表在 ZSet 场景下综合性能更优

❓ 误区 2:“Redis 为什么不用 B+ 树?”

  • B+ 树适合磁盘存储(减少 I/O),而 Redis 是纯内存系统,不需要考虑磁盘页。
  • B+ 树实现更复杂,且内存中跳表的缓存局部性并不差。

七、总结:Redis 选择跳表的核心原因

维度跳表(Skip List)红黑树(RB-Tree)
范围查询⭐️⭐️⭐️ 极其高效(线性遍历)⭐️ 需中序遍历,效率低
代码复杂度⭐️⭐️⭐️ 简单,易维护⭐️ 旋转逻辑复杂
内存开销略高(指针多)较低
并发扩展性⭐️⭐️ 易加锁⭐️ 旋转操作难并发
缓存友好性⭐️⭐️ 底层链表连续⭐️ 节点分散

Redis 的选择逻辑
“在内存系统中,为高频范围查询场景,牺牲少量内存,换取极致的遍历性能和代码简洁性。”


结语

Redis 的每一个设计决策,都是对实际场景、性能、可维护性的深思熟虑。跳表或许不是“最强大”的数据结构,但它是ZSet 场景下的最优解

下次当你调用redisTemplate.opsForZSet().rangeByScore()时,不妨想象一下:此刻,Redis 正在用一条优雅的多层链表,为你飞速定位数据!

视频看了几百小时还迷糊?关注我,几分钟让你秒懂!

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

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

相关文章

Oracle查询表中指定库名,表约束名的上下表依赖关系

查询表中指定库名,表约束名的上下表依赖关系SELECT a.table_name AS 子表名,a.column_name AS 子表关联字段,c.table_name AS 父表名,c.column_name AS 父表关联字段 FROM all_cons_columns a JOIN all_constraints b…

Oracle查询表中指定库名,表约束名的上下表依赖关系

查询表中指定库名,表约束名的上下表依赖关系SELECT a.table_name AS 子表名,a.column_name AS 子表关联字段,c.table_name AS 父表名,c.column_name AS 父表关联字段 FROM all_cons_columns a JOIN all_constraints b…

怒江州泸水 福贡贡山 兰坪英语雅思培训辅导机构推荐,2026权威出国雅思课程中心学校口碑排行榜

在雅思备考热潮持续升温的当下,怒江州泸水、福贡、贡山、兰坪四地怀揣留学梦想的考生,却深陷诸多备考困境:优质雅思培训资源稀缺,难以接触到权威的教学指导;选课过程中信息繁杂,无法精准甄别靠谱的教育机构;不同…

Redis 分布式锁:从原理到 Spring Boot 实战,避开 90% 开发者踩的坑!

视频看了几百小时还迷糊&#xff1f;关注我&#xff0c;几分钟让你秒懂&#xff01; 在分布式系统中&#xff0c;多个服务实例同时操作共享资源&#xff08;如扣减库存、生成订单号&#xff09;时&#xff0c;必须使用分布式锁来保证数据一致性。而 Redis 凭借其高性能和原子操…

哈尔滨市依兰方正宾县巴彦木兰英语雅思培训辅导机构推荐,2026权威出国雅思课程中心学校口碑排行榜

在留学热潮持续升温的当下,雅思成绩作为全球认可度最高的语言能力证明,成为众多学子申请海外院校的“敲门砖”。然而,哈尔滨依兰、方正、宾县、巴彦、木兰等县域地区的雅思考生,常面临优质培训资源匮乏、备考方向迷…

专为上海企业打造:2026年阿里云企业邮箱优质服务商全面解析

上海作为中国经济的核心引擎,聚集了大量跨国企业、创新型中企及初创团队。在数字化转型浪潮中,企业如何通过高效、安全的邮箱服务提升协作效率、降低运营成本?阿里云企业邮箱凭借其技术实力与服务经验,成为上海企业…

Redis 集群(Cluster)详解:从原理到 Spring Boot 实战,彻底告别单点故障!

视频看了几百小时还迷糊&#xff1f;关注我&#xff0c;几分钟让你秒懂&#xff01; 在高并发、大数据量的生产环境中&#xff0c;单机 Redis 早已无法满足需求&#xff1a;内存有限、性能瓶颈、单点故障……一旦宕机&#xff0c;整个系统雪崩&#xff01; 为了解决这些问题&a…

哈尔滨市通河延寿尚志五常英语雅思培训辅导机构推荐,2026权威出国雅思课程中心学校口碑排行榜

在雅思备考热潮持续升温的当下,哈尔滨市通河、延寿、尚志、五常地区的考生却深陷多重困境:优质雅思培训资源地域分布不均,难以精准匹配全阶段备考需求;缺乏权威的测评与推荐指引,在海量教育机构中难以筛选出靠谱的…

2026年企业如何选择?阿里云邮箱优质服务商推荐与全方位对比指南

企业邮箱已从基础通信工具升级为协同办公的核心枢纽。面对市场上众多服务商,如何选择既满足安全需求、又能提升效率的邮箱系统?本文将以阿里云邮箱为例,从技术、功能、服务、成本等维度展开分析。 一、技术架构:云…

保存一条数据到 Redis 的全过程:从客户端到内存存储,深入底层细节(附 Spring Boot 实战)

视频看了几百小时还迷糊&#xff1f;关注我&#xff0c;几分钟让你秒懂&#xff01; 你是否曾好奇&#xff1a;当你在 Java 代码中调用 redisTemplate.opsForValue().set("user:1001", "张三") 时&#xff0c;Redis 内部到底发生了什么&#xff1f; 一条数…

【收藏级】AI大模型学习路线全解析:抓准缺人风口,实现职业跃迁

本文整理了一套完整可落地的AI大模型学习路线&#xff0c;重点点明&#xff1a;后训练&#xff08;SFT、RLHF/DPO&#xff09;与AI-Agent两大方向&#xff0c;是当前工业界人才缺口最大、普通人入局性价比最高的赛道。路线涵盖6大核心模块——大模型基础认知、核心技术&#xf…

Redis 过期与淘汰策略深度解析:从原理到 Spring Boot 实战,彻底搞懂内存管理机制!

视频看了几百小时还迷糊&#xff1f;关注我&#xff0c;几分钟让你秒懂&#xff01; 在使用 Redis 时&#xff0c;你是否遇到过这些问题&#xff1a; 缓存数据明明设置了过期时间&#xff0c;为什么还占着内存不释放&#xff1f;Redis 内存爆了&#xff0c;新数据写不进去&…

PPIO × 商汤 LazyLLM: 一站式构建 Multi-Agent |实操指南

随着大模型技术从单一对话向多智能体&#xff08;Agent&#xff09;协作演进&#xff0c;如何低成本、高效率地完成应用开发与落地成为行业焦点。 近日&#xff0c;PPIO 正式与 LazyLLM 达成深度合作&#xff0c;通过 LazyLLM 的统一接口和灵活的编排能力&#xff0c;配合 PPIO…

2026公务车定制厂家推荐:实力品牌与专业定制方案解析

公务车定制是针对特定行业功能需求、场景适配及使用习惯开展的个性化车辆设计服务,通过对车型性能、配置、外观等方面的专属优化,为政务、警务、民生服务等领域提供适配性更强的出行工具。一、主要业务场景车型特点外…

分析诚信的豪雅新乐学配镜机构,北京靠谱的有哪些?

随着儿童近视率逐年攀升,家长们对近视防控镜片的需求愈发迫切,其中豪雅新乐学作为主流防控镜片之一,因临床数据显示可平均延缓近视加深67%,成为众多家庭的选择。但家长们在挑选配镜机构时,往往被资质是否正规镜片…

收藏!30+程序员破局35岁危机:从Java后端到大厂大模型岗的实战指南

各位30的程序员同行&#xff0c;你是否也曾在深夜对着电脑屏幕陷入沉思&#xff1a;手头的CRUD工作日渐机械&#xff0c;职业晋升通道一眼就能望到尽头&#xff0c;看着身边20多岁的同事轻松驾驭新框架&#xff0c;还能毫无压力地通宵加班——这一刻&#xff0c;你是不是也在怀…

域名系统支撑无人机网络身份认证及IPv6创新应用研究

编者按&#xff1a;中国互联网络信息中心以互联网域名管理技术国家工程实验室为平台&#xff0c;紧扣网络强国与数字中国建设重大战略需求&#xff0c;持续开展了围绕域名系统支撑算力网络、卫星互联网、区块链异构网络、量子电子混合计算网络等下一代互联网服务架构、标识技术…

工业设计公司服务找哪家,京津冀璞新科技优势盘点

2026年制造业与科技产业深度融合,工业设计已成为企业提升产品竞争力、实现品牌价值跃迁的核心支点。无论是医疗器械的人机工学优化、机器人的结构创新,还是新能源产品的外观与功能融合,优质工业设计公司的专业能力直…

录屏老翻车?那是你没遇到sunwoo录屏大师!

做自媒体或者经常需要做教程的朋友&#xff0c;应该都经历过被“录屏”折磨的日子。 用系统自带的 Xbox Game Bar 吧&#xff0c;功能太简陋&#xff0c;想录个带摄像头的窗口都费劲&#xff1b;用那些大名鼎鼎的商业软件吧&#xff0c;要么收费贵得离谱&#xff0c;要么免费版…

收藏级指南|大模型SFT与RL核心训练调优技巧,小白也能看懂

本文系统拆解大模型微调&#xff08;SFT&#xff09;与强化学习&#xff08;RL&#xff09;的核心技术要点&#xff0c;聚焦实操落地能力&#xff0c;专为程序员及大模型入门者打造。SFT部分重点拆解Prompt设计、高质量数据集构建、参数调优逻辑&#xff1b;RL部分深入讲解奖励…