【Redis / 缓存内核】ZSet 与 Stream:skiplist · rax · 消费组
内容提要
本文讨论了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的读指针和未确认表,提供轻量级的消息处理。