java通过redis实现排行榜功能

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
可观测可视化 Grafana 版,10个用户账号 1个月
简介: java通过redis实现排行榜功能
  1. 数据存储规划
    在排行榜中,每个用户都会有一个唯一的标识(ID),同时需要记录该用户的积分(Score)。因此,我们可以将每个用户的ID作为有序集合中的一个元素,将用户的积分作为该元素的分数。

ZADD rank 1000 user1
ZADD rank 2000 user2
ZADD rank 3000 user3
上面的命令向名为rank的有序集合中添加了3个成员,分别是user1、user2和user3,他们的积分分别是1000、2000和3000。

  1. 排行查询操作
    使用Redis的ZREVRANGE命令,可以按照分数从高到低的顺序返回指定数量的元素,也就是排行榜中前N名的用户。

ZREVRANGE rank 0 2 WITHSCORES
上面的命令表示返回有序集合rank中排名前3的用户,同时返回他们对应的积分。执行该命令后,会返回以下结果:

1) "user3"
2) "3000"
3) "user2"
4) "2000"
5) "user1"
6) "1000"
其中,每个元素的前一个返回值是用户的ID,后一个返回值是用户的积分。

如果需要查询某个用户的排行信息,可以使用Redis的ZREVRANK命令,通过用户ID获取该用户的排名。注意,由于排行榜是从1开始计算的,而有序集合是从0开始计算的,因此需要将计算结果加1才能得到正确的排名。

ZREVRANK rank user2
上面的命令表示查询用户user2在排行榜中的排名。执行该命令后,会返回以下结果:

(integer) 1

  1. 排行更新操作
    使用Redis的ZINCRBY命令,可以增加指定用户的积分。如果用户不存在,该命令会自动创建一个新成员并设置初始积分为0,然后再增加积分。

ZINCRBY rank 1000 user1
上面的命令表示将用户user1的积分增加1000。执行该命令后,用户user1的积分变成了2000。

  1. 删减排行榜
    使用Redis的ZREMRANGEBYRANK命令,可以删除有序集合中指定排名范围的成员。例如,可以删除排行榜中前1000名之外的所有用户。

ZREMRANGEBYRANK rank 0 -1001
上面的命令表示删除有序集合rank中除了前1000名之外的所有成员。执行该命令后,排行榜中只剩下前1000名用户。

  1. 排行榜过期时间设置
    如果需要自动清除某个时间段内的排行榜,可以使用Redis的EXPIRE命令为有序集合设置过期时间。

EXPIRE rank 3600
上面的命令表示为有序集合rank设置一个过期时间为3600秒(即1小时)

Java 实现:

import redis.clients.jedis.Jedis;
import java.util.Map;
import java.util.LinkedHashMap;
import java.util.List;

public class RankList {
private static final String REDIS_HOST = "localhost";
private static final int REDIS_PORT = 6379;
private static final String RANK_KEY = "rank";

public static void main(String[] args) {
    // 初始化Jedis客户端
    Jedis jedis = new Jedis(REDIS_HOST, REDIS_PORT);

    // 添加用户信息
    addUser(jedis, "user1", 1000);
    addUser(jedis, "user2", 2000);
    addUser(jedis, "user3", 3000);

    // 查询排行榜前3名
    List<Map.Entry<String, Double>> topUsers = getTopUsers(jedis, 3);
    System.out.println("Rank\tUser ID\tScore");
    for (int i = 0; i < topUsers.size(); i++) {
        Map.Entry<String, Double> entry = topUsers.get(i);
        System.out.printf("%d\t%s\t%.0f\n", i + 1, entry.getKey(), entry.getValue());
    }

    // 更新用户积分
    incrementScore(jedis, "user1", 1000);

    // 查询指定用户的排名信息
    long rank = getUserRank(jedis, "user1");
    System.out.printf("User1's rank: %d\n", rank);

    // 删除排行榜前1000名之外的用户
    removeExtraUsers(jedis, 1000);

    // 关闭Jedis客户端
    jedis.close();
}

// 添加用户信息
public static void addUser(Jedis jedis, String userId, double score) {
    jedis.zadd(RANK_KEY, score, userId);
}

// 查询排行榜前N名用户
public static List<Map.Entry<String, Double>> getTopUsers(Jedis jedis, int limit) {
    return new LinkedHashMap<>(jedis.zrevrangeWithScores(RANK_KEY, 0, limit - 1)).entrySet().stream()
            .sorted(Map.Entry.<String, Double>comparingByValue().reversed())
            .toList();
}

// 更新用户积分
public static void incrementScore(Jedis jedis, String userId, double increment) {
    jedis.zincrby(RANK_KEY, increment, userId);
}

// 查询指定用户的排名
public static long getUserRank(Jedis jedis, String userId) {
    return jedis.zrevrank(RANK_KEY, userId);
}

// 删除排行榜前N名之外的用户
public static void removeExtraUsers(Jedis jedis, int limit) {
    long rank = jedis.zcard(RANK_KEY) - limit;
    if (rank > 0) {
        jedis.zremrangeByRank(RANK_KEY, 0, rank - 1);
    }
}

}

上面的代码中,首先定义了Redis服务器的地址和端口号等常量。然后通过Jedis客户端连接到Redis服务器,在Redis中添加用户信息、查询排行榜等操作。其中,addUser()方法用于添加用户信息,getTopUsers()方法用于查询排行榜前N名用户,incrementScore()方法用于更新用户积分,getUserRank()方法用于查询指定用户的排名,removeExtraUsers()方法用于删除排行榜中前N名之外的用户。

请注意,在上面的代码示例中,为了保证排行榜中元素的有序性,使用了LinkedHashMap来保存排行榜前N名用户的信息,并使用Java 16中的toList()方法将元素转换为列表形式输出。如果使用的是较早版本的Java,可以自行实现一个按照值排序的Comparator类,或者使用其他第三方库(如Guava等)来进行列表操作。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
1月前
|
运维 监控 JavaScript
JAVA村卫生室、诊所云HIS系统源码 支持医保功能
运维运营分系统 1、系统运维:环境管理、应用管理、菜单管理、接口管理、任务管理、配置管理 2、综合监管:统计监管的医疗机构的综合信息,包括医疗业务量、人员配备量、支付分类占比等。 3、系统运营:机构管理、药品目录管理、用户管理、角色管理、字典管理、模板管理、消息管理、运营配置、售后服务、外部系统。
30 0
|
7天前
|
人工智能 前端开发 Java
Java语言开发的AI智慧导诊系统源码springboot+redis 3D互联网智导诊系统源码
智慧导诊解决盲目就诊问题,减轻分诊工作压力。降低挂错号比例,优化就诊流程,有效提高线上线下医疗机构接诊效率。可通过人体画像选择症状部位,了解对应病症信息和推荐就医科室。
146 10
|
9天前
|
缓存 NoSQL Java
使用Redis进行Java缓存策略设计
【4月更文挑战第16天】在高并发Java应用中,Redis作为缓存中间件提升性能。本文探讨如何使用Redis设计缓存策略。Redis是开源内存数据结构存储系统,支持多种数据结构。Java中常用Redis客户端有Jedis和Lettuce。缓存设计遵循一致性、失效、雪崩、穿透和预热原则。常见缓存模式包括Cache-Aside、Read-Through、Write-Through和Write-Behind。示例展示了使用Jedis实现Cache-Aside模式。优化策略包括分布式锁、缓存预热、随机过期时间、限流和降级,以应对缓存挑战。
|
14天前
|
运维 NoSQL 算法
Java开发-深入理解Redis Cluster的工作原理
综上所述,Redis Cluster通过数据分片、节点发现、主从复制、数据迁移、故障检测和客户端路由等机制,实现了一个分布式的、高可用的Redis解决方案。它允许数据分布在多个节点上,提供了自动故障转移和读写分离的功能,适用于需要大规模、高性能、高可用性的应用场景。
16 0
|
17天前
|
存储 缓存 NoSQL
Java手撸一个缓存类似Redis
`LocalExpiringCache`是Java实现的一个本地缓存类,使用ConcurrentHashMap存储键值对,并通过ScheduledExecutorService定时清理过期的缓存项。类中包含`put`、`get`、`remove`等方法操作缓存,并有`clearCache`方法来清除过期的缓存条目。初始化时,会注册一个定时任务,每500毫秒检查并清理一次过期缓存。单例模式确保了类的唯一实例。
15 0
|
21天前
|
存储 NoSQL 数据处理
Redis Lua脚本:赋予Redis更强大的逻辑与功能
Redis Lua脚本:赋予Redis更强大的逻辑与功能
|
27天前
|
缓存 NoSQL Shell
【Redis深度专题】「核心技术提升」探究Redis服务启动的过程机制的技术原理和流程分析的指南(持久化功能分析)
【Redis深度专题】「核心技术提升」探究Redis服务启动的过程机制的技术原理和流程分析的指南(持久化功能分析)
138 0
|
27天前
|
存储 缓存 NoSQL
【Redis深度专题】「核心技术提升」探究Redis服务启动的过程机制的技术原理和流程分析的指南(集群功能分析)(一)
【Redis深度专题】「核心技术提升」探究Redis服务启动的过程机制的技术原理和流程分析的指南(集群功能分析)
293 0
|
28天前
|
缓存 NoSQL Java
Java项目:支持并发的秒杀项目(基于Redis)
Java项目:支持并发的秒杀项目(基于Redis)
26 0