【问题标题】:Redis zrevrangebyscore, sorting other than lexicographical orderRedis zrevrangebyscore,排序以外的字典顺序
【发布时间】:2012-10-04 03:52:11
【问题描述】:

我在 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​​ 代码对它们进行排序。不过好像也不是什么好办法。

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

提前感谢您的帮助。

附: 分数是 50 的倍数

【问题讨论】:

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


    【解决方案1】:

    排序集中的分数支持双精度浮点数,因此可能更好的解决方案是将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")
    

    查看这个问题了解更多详情:Unique scoring for redis leaderboard

    【讨论】:

    • 嗨,Harley,如果分数不是分数而是计数,在这种情况下你怎么做 incby?应该手动吗?
    • Maziyar 我不完全理解你的问题,但我认为你指的是它不再是incrby 的整数?有zincrby 命令可以处理双精度浮点数。
    【解决方案2】:

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

    
    SORT mylist BY weight_*
    

    http://redis.io/commands/sort

    【讨论】:

    • 有趣,我从来没有在redis中使用过list。我去看看。
    【解决方案3】:

    如果您按分数降序显示排行榜,那么我认为上述解决方案不会奏效。而不是仅仅在分数中附加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)会得到正确的顺序

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-24
      • 1970-01-01
      • 2017-03-25
      • 2019-12-24
      • 1970-01-01
      • 2022-06-11
      • 1970-01-01
      • 2020-08-02
      相关资源
      最近更新 更多