2

我已经使用 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​​ 代码对它们进行排序。但这似乎不是一个好方法。

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

在此先感谢您的帮助。

PS分数是50的倍数

4

3 回答 3

3

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

例如(伪代码)

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

这意味着获得相同高分的多个玩家也将根据他们获得该高分的时间进行排序,如下所示

对于玩家 1...

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

对于玩家 2...

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

有关更多详细信息,请参阅此问题:Redis 排行榜的唯一评分

于 2013-03-03T20:20:15.187 回答
0

排序命令的外部权重功能是你的救星


SORT mylist BY weight_*

http://redis.io/commands/sort

于 2012-10-19T06:32:32.653 回答
0

如果您按分数降序显示排行榜,那么我认为上述解决方案不起作用。而不是只是附加timestamp在分数中,你应该附加Long.MAX_VALUE - System.nanoTime()所以你的最终分数代码应该像 -

highscore = 100
timestamp = Long.MAX_VALUE - System.nanoTime();
redis.zadd('myleaderboard', highscore + '.' + timestamp, playerId);

现在,当您致电时,您将获得正确的订单redis.zrevrange('myleaderboard', startIndex, endIndex)

于 2018-11-04T03:31:14.010 回答