【问题标题】:Redis getting sets of user around a given scoreRedis 获取给定分数附近的用户集
【发布时间】:2013-05-11 11:12:10
【问题描述】:

我正在使用redis来实现排行榜。我要解决的问题陈述是 - 给定一个用户,在排行榜中获得高于他的五个用户和低于他的五个用户。

以下是我采用的方法,如果它是最佳的,或者可以做更好的事情,请告诉我:

1. lower_key = zrank('set_name', 'member_name') // get the position of the user in the set
2. higer_key = zcard('set_name') // the total no. of elements in the leaderboard
3. low = max(0, lkey-5) // edge-case if user rank is less than 5.
4. high = min(key+5, higher_key) // edge-case if user rank lies is top-5
5. zrange('set_name', low, high) // get the range between the intervals. 

zrank is O(log(N))
zcard is O(1)
zrange step is O(log(N)+M) 

有没有更好的方法来执行这个操作?

EIDT:其中一个答案提到了太多的来回切换,因此我添加了一个管道,请看一下实现 -

pipeline = self.redis_connection.pipeline()
lkey = pipeline.zrank(leaderboard_name, member)
hkey = pipeline.zcard(leaderboard_name)
inter = int(self.DEFAULT_PAGE_SIZE)/2
low = max(0, key-inter)
high = min(key+inter, hkey)
pipeline.zrange(leaderboard_name, low, high)
return pipeline.execute()

请告诉我你的想法。

【问题讨论】:

  • 也许你应该只使用 noSql 数据库而不是简单的键值存储。
  • 您能否详细说明这将如何产生影响?我听说 redis 的性能非常好,并且是为这些用例定制的。
  • Redis 非常适合实施实时领导板。你在做正确的事。请参阅blog.agoragames.com/blog/2011/01/01/… 以及其他地方的示例。提到平衡@user1077063。

标签: python algorithm redis leaderboard


【解决方案1】:

因此,您当前的方法很好并且有效(除了变量名称中的拼写错误),但需要在客户端和 Redis 服务器之间进行大量来回操作,而这通常是 Redis 的瓶颈所在。在您的情况下,来回是不必要的,因为您实际上可以在单个 LUA 脚本中完成所有操作,然后您可以从客户端将其作为 Redis 命令运行。然后一切都在 Redis 服务器上完成,并且只有一个来回而不是你的情况下的 3 个。

这是我在 LUA 中的做法(未经测试):

local key_idx = redis.call("ZRANK", KEYS[1], ARGV[1])
local card_idx = redis.call("ZCARD", KEYS[1])
local low_idx = math.max(0, key_idx-5)
local high_idx = math.min(key_idx+5, card_idx)
local return_arr = redis.call("ZRANGE", KEYS[1], low_idx, high_idx)
return return_arr

然后你可以从 redis 调用它:

redis-cli eval "$(cat ./myscript.lua)" 1 sorted_set_name, member_name

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-23
  • 1970-01-01
  • 2013-01-07
  • 2016-07-09
  • 1970-01-01
  • 2018-10-19
相关资源
最近更新 更多