Redis zrevrangebyscore,排序除了词典顺序

时间:2012-10-13 14:46:06

标签: ruby-on-rails-3 redis leaderboard

我使用redis中的排序集实现了一个排行榜。我希望按照时间顺序对具有相同分数的用户进行排序,即,首先出现的用户应该排名更高。目前redis支持词典顺序。有没有办法覆盖它。移动号码被用作排序集中的成员。

我想到的一个解决方案是在手机号码前加上时间戳,并维护一个哈希来映射手机号码和时间戳。

$redis.hset('mobile_time', '1234567890', "#{Time.now.strftime('%y%m%d%H%M%S')}")
pref = $redis.hget('mobile_time, '1234567890'')
$redis.zadd('myleaderboard', "1234567890:#{pref}")

通过从哈希添加前缀,我可以在任何情况下获得给定用户的排名。

现在这不是我想要的。这将与我想要的相反。提前到达的用户将被放置在稍后出现的用户之下(两者都具有相同的分数)。

Key for user1 = 201210121953**23**01234567890    score: 400
key for user2 = 201210121253**26**09313123523    score: 400 (3 seconds later)

如果我使用zrevrangebyscore,则user2将高于user1。

但是,有一种方法可以获得所需的排名:

users_with_higher_score_count = $redis.zcount("mysset", "(400", "+inf")
users_with_same_score = $redis.zrangebyscore("mysset", "400", "400")

现在我有正确排序的 users_with_same_score 列表。查看索引我可以计算用户的等级。

获得排行榜。我可以以50的间隔获得成员并通过ruby代码命令它们。但这似乎不是一个好方法。

我想知道是否有更好的方法来做到这一点。或者我可以在解决方案中做出的任何改进。

提前感谢您的帮助。

P.S。 分数是50的倍数

3 个答案:

答案 0 :(得分:3)

有序集合中的分数支持双精度浮点数,因此可能更好的解决方案是将redis分数存储为highscore.timestamp

e.g。 (伪代码)

highscore = 100
timestamp = now()
redis.zadd('myleaderboard', highscore + '.' + timestamp, playerId)

这意味着获得相同高分的多名玩家也将根据他们达到以下高分的时间进行排序

对于玩家1 ...

redis.zadd('myleaderboard', '100.1362345366', "Charles")

对于玩家2 ...

redis.zadd('myleaderboard', '100.1362345399', "Babbage")

有关详细信息,请参阅此问题:Unique scoring for redis leaderboard

答案 1 :(得分:0)

sort命令的外部权重功能是你的救世主


SORT mylist BY weight_*

http://redis.io/commands/sort

答案 2 :(得分:0)

如果您以得分的降序显示排行榜,那么我认为上述解决方案无效。不仅要在分数中附加self,还应附加timestamp,因此最终分数代码应类似于-

Long.MAX_VALUE - System.nanoTime()

现在,当您致电highscore = 100 timestamp = Long.MAX_VALUE - System.nanoTime(); redis.zadd('myleaderboard', highscore + '.' + timestamp, playerId);

时,您将获得正确的订单