【Redis / 缓存内核】ZSet 与 Stream:skiplist · rax · 消费组

💡 原文中文,约6200字,阅读约需15分钟。
📝

内容提要

本文讨论了Redis中的ZSet和Stream的存储结构。ZSet使用字典和跳表双结构,支持高效查找和排序;Stream采用rax树索引和listpack,按时间ID追加日志,消费组实现了至少一次投递语义,适合轻量级消息处理。

🎯

关键要点

  • ZSet使用字典和跳表双结构,支持高效查找和排序。

  • 小ZSet使用listpack存储,超过阈值后升级为跳表和哈希表。

  • 跳表的实现基于William Pugh的算法,允许重复分数并支持反向遍历。

  • Stream采用rax树索引和listpack,按时间ID追加日志,适合轻量级消息处理。

  • 消费组实现了至少一次投递语义,记录未确认的消息。

  • Stream不是独立的消息中间件,而是基于ZSet的读指针和未确认表。

  • ZSet和Stream的设计目标是高效存储和处理数据,适应不同的使用场景。

🔎

延伸解读

ZSet的双结构优势

ZSet结合了字典和跳表的双重结构,提供了高效的查找和排序能力。字典支持O(1)的快速查找,而跳表则允许O(log N)的范围查询和排名。这种设计使得ZSet在处理大量数据时,能够在性能和灵活性之间取得良好的平衡。

Stream的消费组机制

Redis的Stream通过消费组实现至少一次投递语义,适合轻量级消息处理。消费组的设计允许多个消费者并发处理消息,提升了系统的吞吐量。然而,Stream并不是一个完整的消息中间件,用户在使用时需注意其在跨节点分区时的有序性问题。

跳表与红黑树的比较

Redis选择跳表而非红黑树作为ZSet的底层结构,主要是因为跳表实现简单且支持并发扩展。尽管红黑树在最坏情况下提供确定性的O(log n)性能,但跳表在实际应用中表现出更好的灵活性和可维护性,尤其是在Redis的单线程环境下。

延伸问答

ZSet的存储结构是怎样的?

ZSet使用字典和跳表的双结构,字典用于O(1)查找,跳表用于O(log N)的范围和排名操作。

Stream的主要特点是什么?

Stream采用rax树索引和listpack,按时间ID追加日志,适合轻量级消息处理。

ZSet如何处理小数据集?

小ZSet使用listpack存储,当超过阈值后会升级为跳表和哈希表。

消费组在Stream中是如何实现的?

消费组通过读指针和未确认表实现至少一次投递语义,记录未确认的消息。

跳表的实现有什么特别之处?

跳表基于William Pugh的算法,允许重复分数并支持反向遍历,层高由随机算法生成。

Stream与传统消息中间件有什么区别?

Stream不是独立的消息中间件,而是基于ZSet的读指针和未确认表,提供轻量级的消息处理。

🏷️

标签

➡️

继续阅读