✅Redis的zset实现排行榜,实现分数相同按照时间顺序排序,怎么做?

典型回答

在Redis中,使用zset可以实现排行榜的功能这个大家都知道。

zset可以实现,将每个用户的得分作为zset中元素的score,将用户ID作为元素的value。使用zset提供的排序功能,可以按照分数从高到低排序,但是如果分数相同,按照默认的排序规则会按照value值排序,而不是按照时间顺序排序。

为了实现分数相同按照时间顺序排序,我们可以将分数score设置为一个浮点数,其中整数部分为得分,小数部分为时间戳,如下所示:

score = 分数 + 时间戳/1e13

假设现在的时间戳是1680417299000,除以1e13得到0.1680417299000,再加上一个固定的分数(比如10),那么最终的分数就是10.1680417299000,可以将它作为zset中某个成员的分数,用来排序。

这么做了之后,假如有四个数字:

10.1680417299000、10.1680417299011、11.1680417299000、11.1680417299011

他们按照倒序拍完顺序之后,会是:

11.1680417299011>11.1680417299000>10.1680417299011>10.1680417299000

实现了分数倒序排列,分数相同时间戳大的排在了前面,这和我们的需求相反了,所以,就需要在做一次转换。

score = 分数 + 1-时间戳/1e13

因为时间戳是这种形式1708746590000 ,共有13位,而1e13是10000000000000,即1后面13个0,所以用时间戳/1e13就能得到一个小数

这样可以保证分数相同时,按照时间戳从小到大排序,即先得分的先被排在前面。

代码实现如下:

import redis.clients.jedis.Jedis;
/**
*@author Hollis
**/
public class RedisZsetDemo {
    private static final String ZSET_KEY = "my_zset";

    public static void addMember(String member,Int score, long timestamp, Jedis jedis) {
        double final_score = score + 1 - timestamp / 1e13;
        jedis.zadd(ZSET_KEY, final_score, member);
    }
}

原文: https://www.yuque.com/hollis666/xkm7k3/ooqi2qfep22bcpag