Redis - ZSet底层数据结构
ZSet对象编码是ziplist或者 skiplist。
在同时满足以下两个条件时使用ziplist:
1)有序集合保存的元素数量小于128个;
2)有序集合保存的所有元素的长度小于64字节;
不能满足上面任何一个条件时则使用 skiplist 编码。
注意:以上两个条件也可以通过Redis配置文件zset-max-ziplist-entries 和 zset-max-ziplist-value 进行修改。
ZSet实现思路
ziplist数据结构
ziplist 编码的 Zset,每个集合元素使用两个紧挨在一起的压缩列表结点来保存,第一个结点保存元素的成员(member),第二个结点保存元素的分值(score) 。ziplist 内的集合元素按 score 从小到大排序,其实质是一个双向链表。虽然元素是按 score 有序排序的,但对 ziplist 的节点指针只能线性地移动,此时查找某个给定元素的复杂度为 O(N)。
相邻的元素,整体数据是有序格式。
skiplist数据结构
skiplist 编码的 Zset,核心点主要包括一个skiplist(跳跃表)对象和一个dict(字典)对象。跳跃表按 score 有序地(从小到大)保存所有集合元素,每个元素包括元素和分值,查找时间复杂度为平均 O(logN),最坏 O(N) ;字典则保存着从 member 到 score 的映射,这样就可以用 O(1)的复杂度来查找 member 对应的 score 值。虽然同时使用两种结构,但它们会通过指针来共享相同元素的 member 和 score,因此不会浪费额外的内存。
简单说来跳跃表(查看实现原理)也是链表的一种,只不过它在双向链表的基础上增加了跳跃功能(多层索引,空间换时间),正是这个跳跃的功能,使得在查找、插入、删除元素时,跳跃表能够提供O(logN)的时间复杂度。
为什么zset数据类型既支持高效的范围查询且能以O(1)的时间复杂度获取元素权重值?
高效的范围查询是因为它的核心数据结构是跳跃表,而能以O(1)的时间复杂度获取元素权重值是因为同时采用了哈希表进行索引。
为什么 Redis 要用跳表来实现Zset而不是红黑树、B+树?(查看原文)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」