Redis 基础教程

Redis 命令

Redis 高级教程

Redis 笔记

Redis ZRANGEBYSCORE 命令

Redis 有序集合 Redis 有序集合


Redis ZRANGEBYSCORE 命令返回有序集合的指定 key 中,所有 score 值介于 min 和 max 之间(包含等于 min 和 max)的成员(默认情况下),也可以通过给 min 和 max 对应参数前增加 ( 符号来使用可选的开区间(小于或大于)。有序集合成员按 score 值递增(从小到大)顺序排列;此外,具有相同 score 值的成员按字典序(lexicographical order)来排列(该属性是有序集提供的,不需要额外的计算)

命令格式

ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]

可用版本:>=1.0.5

时间复杂度:O(log(N)+M),N 为有序集合的基数(成员个数),M 为指定的返回条数。如果 M 为常数(例如,始终要求使用 LIMIT 获取前 10 个元素),则可以将其视为 O(log(N))。

命令参数

参数名 可选 参数解释
min 必需 最小的 score(分数)值。
max 必需 最大的 score(分数)值。
WITHSCORES 可选 该参数将有序集成员及其 score 值一起返回。该选项自 Redis 2.0 版本起可用
LIMIT offset count 可选 取值的范围,offset、表示结果的起始位置(或偏移位置),count、表示返回结果的数量。值得注意的是,当 offset 很大时,定位 offset 的操作可能需要遍历整个有序集,此过程最坏复杂度为 O(N)

补充:

  • min 和 max 可以是 -inf 和 +inf,这样一来,你就可以在不知道有序集的最低和最高 score 值的情况下,使用 ZRANGEBYSCORE 这类命令。
  • 默认情况下,区间的取值使用闭区间(包含阈值),也可以通过给定参数前增加 ( 符号来使用可选的开区间。

举个例子:

ZRANGEBYSCORE zset (1 88

返回所有符合条件 1 < score <= 88 的成员,而

ZRANGEBYSCORE zset (88 (100

则返回所有符合条件 88 < score < 100 的成员。

命令返回值

返回指定区间内,带有 score 值(可选项)的有序集成员的列表。

使用场景

排行榜

各类(用户或物品)排行榜可采用 Redis 的有序集合结构,其中成员对应用户 id 或物品 id,分数对应其分数。

用户实时行为

在搜索推荐系统中,经常会把用户最近的一些行为作为重要的特征,我们可以借助于 Redis 的有序集合数据结构保存用户相关的行为(如搜索、点击、关注等等),key 为行为标识与用户标识组合而成,如  search_click_188 表示用户 188 的搜索点击数据相关 key,成员对应相应行为的 item_id(或 user_id),分数(score)一般存储对应行为发生的时间戳,一般情况下精确到秒即可。

带有权重的元素的随机选择

有一个常见的场景,就是从集合中随机选择一个元素,但是不同的元素具有不同的权重,对应权重影响对应元素的被选择概率。

对此,我们可以借助 Redis 的 ZRANGEBYSCORE 命令解决该问题。

假设您有元素 A,B 和 C 的权重为 1、2 和 3。您计算权重之和,即 1 + 2 + 3 = 6,此时,您可以使用以下算法将所有元素添加到排序集中:

SUM = ELEMENTS.TOTAL_WEIGHT // 6 in this case.
SCORE = 0
FOREACH ELE in ELEMENTS
    SCORE += ELE.weight / SUM
    ZADD KEY SCORE ELE
END

这意味着我们做了如下操作:

A to score 0.16
B to score 0.5
C to score 1

此时,如果每次想要获得加权随机元素时,只需计算介于 0 和 1 之间的随机数即可,因此操作如下:

RANDOM_ELE = ZRANGEBYSCORE key RAND() +inf LIMIT 0 1

注:其中 RAND() 为命令写入时,生成的随机数,并非 Redis 自带的命令(或函数)

示例

redis> ZADD beer 1 ale
(integer) 1
redis> ZADD beer 2 lager
(integer) 1
redis> ZADD beer 3 wild
(integer) 1
redis> ZRANGEBYSCORE beer 1 2              # 分数在闭区间 1 到 2 的成员
1) "ale"
2) "lager"
redis> ZRANGEBYSCORE beer (1 2             # 分数在半开半闭区间 1 到 2 的成员
1) "lager"
redis> ZRANGEBYSCORE beer (1 (2            # 分数在开区间 1 到 2 的成员
(empty list or set)
redis> ZRANGEBYSCORE beer -inf +inf        # 返回所有的成员
1) "ale"
2) "lager"
3) "wild"
redis> ZRANGEBYSCORE beer 1 (3 WITHSCORES  # 分数在半闭半开区间 1 到 3 的成员及分数
1) "ale"
2) "1"
3) "lager"
4) "2"
redis> ZRANGEBYSCORE beer 1 3 LIMIT 1 2    # 分数在闭区间 1 到 3 的成员,并以 1 为偏移量,返回 2 个成员
1) "lager"
2) "wild"