Redis中的Zset是怎么实现的?
注意
内容来源网络,仅供学习使用。
不要相信文档中的链接、联系方式等!!!
Redis中的Zset是怎么实现的?
典型回答
ZSet(也称为Sorted Set)是Redis中的一种特殊的数据结构,它内部维护了一个有序的字典,这个字典的元素中既包括了一个成员(member),也包括了一个double类型的分值(score)。这个结构可以帮助用户实现记分类型的排行榜数据,比如游戏分数排行榜,网站流行度排行等。
Redis中的ZSet在实现中,有多种结构,大类的话有两种,分别是ziplist(压缩列表)和skiplist(跳跃表),但是这只是以前,在Redis 5.0中新增了一个listpack(紧凑列表)的数据结构,这种数据结构就是为了替代ziplist的,而在之后Redis 7.0的发布中,在Zset的实现中,已经彻底不在使用zipList了。

当ZSet的元素数量比较少时,Redis会采用ZipList(ListPack)来存储ZSet的数据。ZipList(ListPack)是一种紧凑的列表结构,它通过连续存储元素来节约内存空间。当ZSet的元素数量增多时,Redis会自动将ZipList(ListPack)转换为SkipList,以保持元素的有序性和支持范围查询操作。
在这个过程中,Redis会遍历ZipList(ListPack)中的所有元素,按照元素的分数值依次将它们插入到SkipList中,这样就可以保持元素的有序性。
在Redis的ZSET具体实现中,SkipList的这种实现,不仅用到了跳表,还会用到dict(字典)

其中,SkipList用来实现有序集合,其中每个元素按照其分值大小在跳表中进行排序。跳表的插入、删除和查找操作的时间复杂度都是 O(log n),可以保证较好的性能。
dict用来实现元素到分值的映射关系,其中元素作为键,分值作为值。哈希表的插入、删除和查找操作的时间复杂度都是 O(1),具有非常高的性能。

扩展知识
何时转换
ZipList(ListPack)和SkipList之间是什么时候进行转换的呢?
在 Redis 中,ZSET在特定条件下会使用 ziplist作为其内部表示。这通常发生在有序集合较小的时候,具体条件如下:
- 元素数量少:集合中的元素数量必须小于某个阈值(zset-max-ziplist-entries)。
- 元素大小小:集合中的每个元素(包括值和分数)的大小必须小于指定的最大值(zset-max-ziplist-value)。
默认情况下,zset-max-ziplist-entries是128,zset-max-ziplist-value是64。
总的来说就是,当元素数量少于128,每个元素的长度都小于64字节的时候,使用ZipList(ListPack),否则,使用SkipList!
跳表

