redis中的zset(有序集)

Zset相关问题是面试中的高频问题。那么zset到底是什么?底层的实现原理是什么?有哪些相关的使用场景?

什么是1。zset?

在redis官网看到的(/commands.html#sorted_set)。有兴趣的同学可以直接去看。

ZADD关键得分1值1得分2值2........

也就是说,可以添加yes分值组和值组,并且可以同时添加多个组。

?4.zset实现

在redis.conf中,有如下两个参数:

zset-max-zip list-entries 128

zset-max-ziplist-value 64

这两个条件都不满足,所以我们用ziplist压缩表来实现有序集。

如果满足这两个条件中的一个,排序集的内部实现将从ziplist转换为zset。

Zset-Max-ziplist-Entries 128,即当排序集合中的元素对超过128(存储了score和值的元素对,所以数据项为256)时,内部实现会从zip list转换为Zset。

Zset-max-ziplist-value 64,即任意值的长度超过64字节,内部实现将从ziplist转换为Zset。

Zset由dict和skiplist实现。

5.?Ziplist,即压缩列表

压缩列表是由连续内存组成的顺序数据结构。压缩列表可以包含任意数量的条目,每个条目可以包含一个字节数组或一个整数。

压缩后的链表头有三个字段:zlbytes、zltail和zllen分别代表链表的长度(整个链表所占的字节数)、链表尾部的偏移量(从尾部节点到起始地址的字节数)和链表中的条目数。

列表末尾还有一个zlend,表示列表结束。

6.skiplist

从上图的压缩列表可以看出,如果我们寻找第一个元素或者最后一个元素,可以直接通过头中三个字段的长度来定位。复杂度为O(1),但如果寻找其他元素,只能顺序寻找,复杂度为O(n)。为了解决这个问题,我们可以使用跳表。

在添加节点之前,也会对其进行查询以确定插入位置,然后完成插入操作。同时,将实现排序集合的排序。

跳表中新添加的节点不会影响其他节点的索引位置。因此插入操作只需要修改插入节点前后的指针,不需要修改所有节点,降低了插入的复杂度,因此跳表在插入性能上明显优于平衡树。

?7.ZSET的使用场景

需要排序的场景,比如top10热门文章或者排行榜。

对于消息的延迟发送,使用score来存储发送时间戳,任务定期扫描已排序的集合来确定发送时间。