V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
imherer
V2EX  ›  程序员

请教一个 redis SortedSet 排序问题

  •  
  •   imherer · 2017-04-17 11:33:30 +08:00 · 3587 次点击
    这是一个创建于 2772 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近在用 redis 的 SortedSet 做积分排行榜,降序排列。 SortedSet 默认同样的积分后达到的排名靠前(降序) 即假如我现在有个 key 为rank的里面有如下 member:

    m1:10
    m2:20
    

    按降序排的话应该是:m2>m1 假如这时候又来了 m3 ,积分也是 20 分,按照 SortedSet 的排序应该是:m3>m2>m1 但我们很多时候需求是 同样的积分谁先达到谁排名靠前,即想要的结果应该是:m2>m3>m1

    各位有这样的需求吗?都是怎么处理的呢?

    22 条回复    2018-08-16 17:25:56 +08:00
    bbao
        1
    bbao  
       2017-04-17 12:15:54 +08:00
    增加一个时间维度
    frazy
        2
    frazy  
       2017-04-17 12:26:36 +08:00
    拿出来的时候,计费相同自己再倒叙下不就行了
    frazy
        3
    frazy  
       2017-04-17 12:26:53 +08:00
    计费=积分
    hand515
        4
    hand515  
       2017-04-17 13:23:53 +08:00
    zadd 后,往另外一个 key 插入上报时间。
    排序有相同的,按另外一个 key 排
    imherer
        5
    imherer  
    OP
       2017-04-17 13:49:08 +08:00
    @hand515 这个好像可行
    JKeita
        6
    JKeita  
       2017-04-17 13:54:44 +08:00
    存储里的值权重值根据:时间+积分,进行计算;比如时间戳+积分;实际积分值存到另一个对象里
    imherer
        7
    imherer  
    OP
       2017-04-17 14:10:35 +08:00
    @JKeita 有道理
    fds
        8
    fds  
       2017-04-17 14:33:54 +08:00
    这种情况一般把时间加载用小数点后,不过得注意精度问题。如果是赛季那种有开始结束时间的就比较简单。
    imherer
        9
    imherer  
    OP
       2017-04-17 15:18:13 +08:00
    @fds 这样?
    10.1492413455578
    20.1492413455590
    20.1492413485431
    xiaowangge
        10
    xiaowangge  
       2017-04-17 15:20:57 +08:00
    看积分的上限是多少,如果积分上限不大的话,可以:


    时间戳 乘以某个数值,例如:

    写操作: timeStamp * 1000000 + 积分

    查询操作,获得结果后再 除以 1000000
    imherer
        11
    imherer  
    OP
       2017-04-17 15:21:36 +08:00
    @xiaowangge 嗯,这样也可以。谢谢
    jiangzhuo
        12
    jiangzhuo  
       2017-04-17 15:24:11 +08:00
    把分数乘以-1 计入 redis
    jiangzhuo
        13
    jiangzhuo  
       2017-04-17 15:35:24 +08:00
    @jiangzhuo 哎呀忘记 redis 相同 score 默认是按照字幕顺序排的了。我们用的老版本 redis 修改的
    fds
        14
    fds  
       2017-04-17 15:43:01 +08:00
    @imherer 全写上精度可能不够,所以还是先定个范围。比如一个月为周期的话,月初的积分加上 0.9 ,月末的积分加上 0.1 ,中间按时间比例插值。当然得结合积分本身估算下精度。以十年为周期的话,精度应该也能达到天吧。
    imherer
        15
    imherer  
    OP
       2017-04-17 15:47:15 +08:00
    @fds 嗯。
    silenceeeee
        16
    silenceeeee  
       2017-04-17 16:36:59 +08:00
    时间戳 + 积分,这样好像有问题吧
    会员 m1 的积分是 2 ,时间戳是 100 ,那么排序权值为 103
    会员 m2 的积分是 1 ,时间戳是 103 ,那么排序权值为 104
    这样降序排列的时候, m2 岂不是排在了 m1 之前?

    或者是我哪里理解的不对?
    @JKeita
    silenceeeee
        17
    silenceeeee  
       2017-04-17 16:38:19 +08:00
    接上条回复: 会员 m1 的积分是 2 ,时间戳是 100 ,那么排序权值为 102 (不是 103 ) 但是不影响我列举的示例(发过的评论不能修改,有点蛋疼)
    JKeita
        18
    JKeita  
       2017-04-17 17:08:34 +08:00
    @JKeita 只是举个例子,实际权重计算方式根据业务实际情况进行设计
    JKeita
        19
    JKeita  
       2017-04-17 17:09:39 +08:00
    @silenceeeee 艾特错了,楼上我的回复
    silenceeeee
        20
    silenceeeee  
       2017-04-17 17:56:29 +08:00
    @JKeita 了解了。你的意思只是说把时间戳作为权重因子,但不是简单的加减,我觉得把时间戳放在小数点后就很靠谱嘛
    zjuhwc
        21
    zjuhwc  
       2017-04-18 08:16:58 +08:00 via iPhone
    分数存成:分数-时间戳 /10 的 9 次方
    晚到达的分数会小一点,要拿到准确分数向上取整就行,我们以前就这么干的
    nextzeus
        22
    nextzeus  
       2018-08-16 17:25:56 +08:00
    搞来搞去 还不如用数据库去二维排序最准确
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4973 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 09:50 · PVG 17:50 · LAX 01:50 · JFK 04:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.