Redis 的 Zset
回答
-
ZSet(Sorted Set)内部维护了一个有序的字典,这个字典的元素中既包括了一个成员(member),也包括了一个double类型的分值(score)。
这种结构可以帮助用户实现记分类型的排行榜数据。
比如:游戏分数排行榜,网站流行度排行等。
-
Redis 中的 ZSet 在实现中,有多种结构。
-
ZSet 如何选择存储结构?
-
当 ZSet 的元素数量比较少时,Redis会采用 **ZipList(ListPack)**来存储ZSet的数据。
ZipList(ListPack)是一种紧的列表结构,它通过连续存储元素来节约内存空间。
-
当 ZSet 的元素数量增多时,Redis会自动将 ZipList(ListPack)转换为SkipList,以保持元素的有序性和支持范围查询操作。
在这个转换过程中,Redis 会历 ZipList(ListPack)中的所有元素,按照元素的分数值依次将它们插入到 SkipList 中,这样就可以保持元素的有序性。
-
-
在 Redis 的 ZSet 具体实现中,不仅用到了SkipList (跳表),还会用到 dict(字典)。
-
-
-
SkipList 用来实现有序集合,
其中,每个元素按照其分值大小在跳表中进行排序。
跳表的插入、删除、查找 操作的时间复杂度都是
O(logn)
,可以保证较好的性能。 -
dict 用来实现元素到分值的映射关系
其中元素作为键,分值作为值。
哈希表的插入、删除、查找 操作的时间复杂度都是
O(1)
,具有非常高的性能
扩展
1、ZipList(ListPack)-> SkipList,如何转换的呢?
-
元素数量少
集合中的元素数量必须小于某个值
(zset-max-ziplist-entries)
zset-max-ziplist-entries 默认是 128
-
元素大小小
集合中的每个元素(包括值和分数)的大小必须小于指定的最大值
(zset-max-ziplist-value)
zset-max-ziplist-value 默认是 64
-
总体来说,当元素数量少于 128,每个元素的长度都小于 64 字节的时候,使用ZipList(ListPack),否则,使用 SkipList。