Redis 排序集和解决关系

idr*_*rig 5 lua sortedset redis

我正在使用 Redis 排序集来存储我正在处理的项目的排名。我们没有预料到(!)我们想要如何处理关系。Redis 按字典顺序对具有相同分数的条目进行排序,但我们想要做的是对具有相同分数的所有条目给予相同的排名,例如在以下情况

redis 127.0.0.1:6379> ZREVRANGE foo 0 -1 WITHSCORES
1) "first"
2) "3"
3) "second3"
4) "2"
5) "second2"
6) "2"
7) "second1"
8) "2"
9) "fifth"
10) "1"
Run Code Online (Sandbox Code Playgroud)

我们要考虑second1second2和,second3因为它们都具有位置 2,并且fifth具有位置 5。因此,第三或第四位置没有条目。 ZREVRANK在这里没有用,那么获得我正在寻找的号码的最佳方法是什么?

idr*_*rig 4

在我看来,一种方法是编写一个小 Lua 脚本并使用该EVAL命令。结果运算仍然具有对数复杂度。

例如,假设我们对 的位置感兴趣second2。在脚本中,首先我们使用 获得其分数ZSCORE,获得 2。然后我们使用 获得具有该分数的第一个条目ZRANGEBYSCORE,获得second3。我们所追求的位置就是ZREVRANKsecond31。

redis 127.0.0.1:6379> ZSCORE foo second2
"2"
redis 127.0.0.1:6379> ZREVRANGEBYSCORE foo 2 2 LIMIT 0 1
1) "second3"
redis 127.0.0.1:6379> ZREVRANK foo second3
(integer) 1
Run Code Online (Sandbox Code Playgroud)

所以脚本可能是这样的

local score = redis.call('zscore', KEYS[1], ARGV[1])
if score then
  local member = redis.call('zrevrangebyscore', KEYS[1], score, score, 'limit', 0, 1)
  return redis.call('zrevrank', KEYS[1], member[1]) + 1
else return -1 end
Run Code Online (Sandbox Code Playgroud)

  • 这仅适用于您设计的条目列表。例如,如果您有两个人并列第一,则 ZREVRANK 调用将不会返回您想要的值。 (2认同)