Redis 中的有序集合详解

· 约 7 分钟读完

介绍

Redis 是一款高性能的键值对存储系统,提供了丰富的数据结构,其中包括有序集合(Sorted Set)。有序集合是一种基于哈希表和跳跃表实现的散列表,它可以存储一组带有分数的元素,并且可以按照分数从小到大或者从大到小的顺序排列元素,同时每个元素都有唯一的键值。

有序集合是一个非常实用的数据结构,它可以用来存储排行榜、社交网络关系、优先级队列等需要有序排列的数据。本文将详细讲解 Redis 中的有序集合的使用方法和底层实现原理。

基本操作

有序集合的基本操作包括添加元素、删除元素、更新元素分数、获取元素排名和分数等。下面分别介绍这些操作的使用方法。

添加元素

添加元素的操作可以使用 ZADD 命令,命令格式为:

其中,key 是有序集合的键值,score 是元素的分数,member 是元素的键值。可以通过多次指定 score 和 member 参数添加多个元素:

删除元素

删除元素的操作可以使用 ZREM 命令,命令格式为:

其中,key 是有序集合的键值,member 是要删除的元素的键值。可以同时删除多个元素:

更新元素分数

更新元素分数的操作可以使用 ZINCRBY 命令,命令格式为:

其中,key 是有序集合的键值,increment 是要增加的分数(可以是负数),member 是要更新的元素的键值。如果元素不存在,会自动添加并设置初始分数为 increment:

获取元素排名

获取元素排名的操作可以使用 ZRANK 命令和 ZREVRANK 命令,命令格式分别为:

其中,key 是有序集合的键值,member 是要查询排名的元素的键值。ZRANK 命令返回元素在有序集合中从小到大排列的排名(排名从 0 开始计数),ZREVRANK 命令返回元素在有序集合中从大到小排列的排名。

获取元素分数

获取元素分数的操作可以使用 ZSCORE 命令,命令格式为:

其中,key 是有序集合的键值,member 是要查询分数的元素的键值。如果元素不存在,返回 nil。

底层实现原理

有序集合的底层实现基于哈希表和跳跃表两种数据结构。

哈希表负责元素的键值到元素本身的映射,每个元素对应着一个哈希表的键值对。为了支持元素的分数排序,每次添加元素的同时会将元素键值和分数作为参数,将它们以字典序递增的方式拼接成字符串,然后将该字符串作为哈希表的键值,元素本身作为哈希表的值。

跳跃表负责元素的分数排序和排名计算,每个元素对应着一个跳跃表的节点。跳跃表是一种基于多层链表的数据结构,每一层都是一个有序的单链表,每个节点包括若干个指向下一层节点的指针。在查询元素排名时,可以从跳跃表的最高层开始,沿着对应元素分数递减的路径遍历跳跃表,直到找到对应元素的节点,统计该节点之前的元素个数即可得到排名。

示例代码

下面是一个使用有序集合的示例程序,它模拟从数亿条日志中提取前 10 名的关键词排名。假设每个日志的格式如下:

程序通过正则表达式解析每个日志中的关键词和查询时间,并使用有序集合记录每个关键词的查询次数和平均查询时间。最后,程序从有序集合中查询前 10 名关键词及其排名、查询次数和平均查询时间,输出到控制台。

在使用该示例程序前,需要先创建一个名为 word_rank 的有序集合和一个名为 word_time 的有序集合:

启动程序后,它会从 logs.txt 文件中读取日志并更新有序集合。当所有日志都读取完成后,它会从有序集合中查询前 10 名关键词并输出到控制台。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d7e64fa941bf7134e209fc