Redis 排行榜:实现、操作与性能优化

Redis 是一个高性能的内存数据库,支持多种数据结构,其中有序集合(Sorted Set)特别适合用于实现排行榜功能。本文将详细介绍如何使用 Redis 的有序集合实现一个简单而高效的排行榜系统,包括排行榜的基本操作、示例代码以及优化建议。

一,有序集合(Sorted Set)简介

有序集合是 Redis 提供的一种数据结构,它结合了集合和有序列表的特点。每个元素都有一个唯一的成员和一个分数,Redis 会根据分数对元素进行排序。常用的有序集合命令包括:

  • ZADD:向有序集合添加元素。
  • ZREM:移除有序集合中的元素。
  • ZINCRBY:增加有序集合中元素的分数。
  • ZRANGE:按分数从低到高获取有序集合中的元素。
  • ZREVRANGE:按分数从高到低获取有序集合中的元素。
  • ZRANK:获取元素在有序集合中的排名(从低到高)。
  • ZREVRANK:获取元素在有序集合中的排名(从高到低)。

二,实现排行榜的基本操作

1. 添加或更新分数

使用 ZADD 命令向排行榜中添加新用户或更新用户的分数。

import redis.clients.jedis.Jedis;public class Leaderboard {private Jedis jedis;private String leaderboardKey = "leaderboard";public Leaderboard() {jedis = new Jedis("localhost", 6379);}// 添加或更新用户分数public void addOrUpdateUserScore(String user, double score) {jedis.zadd(leaderboardKey, score, user);}
}

2. 获取前 N 名用户

使用 ZREVRANGE 命令按分数从高到低获取排行榜中的前 N 名用户。

import java.util.Set;public class Leaderboard {// 获取前 N 名用户public Set<String> getTopNUsers(int n) {return jedis.zrevrange(leaderboardKey, 0, n - 1);}
}

3. 获取用户的排名和分数

使用 ZREVRANK 命令获取用户在排行榜中的排名,使用 ZSCORE 命令获取用户的分数。

public class Leaderboard {// 获取用户排名(从高到低)public Long getUserRank(String user) {return jedis.zrevrank(leaderboardKey, user);}// 获取用户分数public Double getUserScore(String user) {return jedis.zscore(leaderboardKey, user);}
}

4. 删除用户

使用 ZREM 命令从排行榜中删除用户。

public class Leaderboard {// 删除用户public void removeUser(String user) {jedis.zrem(leaderboardKey, user);}
}

三,示例代码

以下是一个完整的示例代码,展示了如何使用 Redis 实现一个简单的排行榜系统。

import redis.clients.jedis.Jedis;import java.util.Set;public class Leaderboard {private Jedis jedis;private String leaderboardKey = "leaderboard";public Leaderboard() {jedis = new Jedis("localhost", 6379);}// 添加或更新用户分数public void addOrUpdateUserScore(String user, double score) {jedis.zadd(leaderboardKey, score, user);}// 获取前 N 名用户public Set<String> getTopNUsers(int n) {return jedis.zrevrange(leaderboardKey, 0, n - 1);}// 获取用户排名(从高到低)public Long getUserRank(String user) {return jedis.zrevrank(leaderboardKey, user);}// 获取用户分数public Double getUserScore(String user) {return jedis.zscore(leaderboardKey, user);}// 删除用户public void removeUser(String user) {jedis.zrem(leaderboardKey, user);}public static void main(String[] args) {Leaderboard leaderboard = new Leaderboard();// 添加或更新用户分数leaderboard.addOrUpdateUserScore("user1", 100.0);leaderboard.addOrUpdateUserScore("user2", 200.0);leaderboard.addOrUpdateUserScore("user3", 150.0);// 获取前 2 名用户Set<String> topUsers = leaderboard.getTopNUsers(2);System.out.println("Top 2 users: " + topUsers);// 获取用户排名和分数Long rank = leaderboard.getUserRank("user1");Double score = leaderboard.getUserScore("user1");System.out.println("User1 rank: " + rank + ", score: " + score);// 删除用户leaderboard.removeUser("user1");System.out.println("User1 removed.");}
}

四,优化建议

1. 使用管道(Pipeline)

当需要批量执行多个命令时,可以使用管道(Pipeline)来减少网络延迟,提高性能。

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;public class Leaderboard {private Jedis jedis;private String leaderboardKey = "leaderboard";public Leaderboard() {jedis = new Jedis("localhost", 6379);}// 批量添加或更新用户分数public void addOrUpdateUserScores(Map<String, Double> userScores) {Pipeline pipeline = jedis.pipelined();for (Map.Entry<String, Double> entry : userScores.entrySet()) {pipeline.zadd(leaderboardKey, entry.getValue(), entry.getKey());}pipeline.sync();}public static void main(String[] args) {Leaderboard leaderboard = new Leaderboard();// 批量添加或更新用户分数Map<String, Double> userScores = new HashMap<>();userScores.put("user1", 100.0);userScores.put("user2", 200.0);userScores.put("user3", 150.0);leaderboard.addOrUpdateUserScores(userScores);// 获取前 2 名用户Set<String> topUsers = leaderboard.getTopNUsers(2);System.out.println("Top 2 users: " + topUsers);}
}

2. 使用缓存

如果排行榜数据不会频繁变化,可以将排行榜结果缓存到内存中,减少对Redis的频繁访问。

import redis.clients.jedis.Jedis;import java.util.HashMap;
import java.util.Map;
import java.util.Set;public class Leaderboard {private Jedis jedis;private String leaderboardKey = "leaderboard";private Map<Integer, Set<String>> cache = new HashMap<>();public Leaderboard() {jedis = new Jedis("localhost", 6379);}// 获取前 N 名用户,使用缓存public Set<String> getTopNUsers(int n) {if (cache.containsKey(n)) {return cache.get(n);} else {Set<String> topUsers = jedis.zrevrange(leaderboardKey, 0, n - 1);cache.put(n, topUsers);return topUsers;}}public static void main(String[] args) {Leaderboard leaderboard = new Leaderboard();// 添加或更新用户分数leaderboard.addOrUpdateUserScore("user1", 100.0);leaderboard.addOrUpdateUserScore("user2", 200.0);leaderboard.addOrUpdateUserScore("user3", 150.0);// 获取前 2 名用户,使用缓存Set<String> topUsers = leaderboard.getTopNUsers(2);System.out.println("Top 2 users: " + topUsers);}
}

3. 使用分片(Sharding)

对于大规模的排行榜,可以使用分片技术,将数据分布到多个Redis实例中,减少单个实例的压力。

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis;import java.util.ArrayList;
import java.util.List;public class ShardedLeaderboard {private ShardedJedis shardedJedis;public ShardedLeaderboard() {List<JedisShardInfo> shards = new ArrayList<>();shards.add(new JedisShardInfo("localhost", 6379));shards.add(new JedisShardInfo("localhost", 6380));shardedJedis = new ShardedJedis(shards);}// 添加或更新用户分数public void addOrUpdateUserScore(String user, double score) {shardedJedis.zadd("leaderboard", score, user);}// 获取前 N 名用户public Set<String> getTopNUsers(int n) {return shardedJedis.zrevrange("leaderboard", 0, n - 1);}public static void main(String[] args) {ShardedLeaderboard leaderboard = new ShardedLeaderboard();// 添加或更新用户分数leaderboard.addOrUpdateUserScore("user1", 100.0);leaderboard.addOrUpdateUserScore("user2", 200.0);leaderboard.addOrUpdateUserScore("user3", 150.0);// 获取前 2 名用户Set<String> topUsers = leaderboard.getTopNUsers(2);System.out.println("Top 2 users: " + topUsers);}
}

通过以上优化建议,开发者可以进一步提升Redis排行榜系统的性能和可扩展性,确保在高并发和大数据量的情况下依然能够高效运行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/881832.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从零开始构建:Python自定义脚本自动化你的日常任务

从零开始构建&#xff1a;Python自定义脚本自动化你的日常任务 Python 作为一种简洁且功能强大的编程语言&#xff0c;被广泛应用于各种自动化任务中。通过编写 Python 脚本&#xff0c;你可以轻松地将日常重复性工作自动化&#xff0c;例如文件操作、数据处理、网络爬虫、系统…

vue3--通用 button 组件实现

背景 在日常开发中,我们一般都是利用一些诸如:element-ui、element-plus、ant-design等组件库去做我们的页面或者系统 这些对于一些后台管理系统来说是最好的选择,因为后台管理系统其实都是大同小异的,包括功能、布局结构等 但是对于前台项目,比如官网、门户网站这些 …

软考中级 - 软件设计师学习笔记 - 1.2 计算机体系结构

1.2.1 计算机体系结构的发展 按处理机的数量&#xff08;宏观上&#xff09; 单处理系统&#xff1a;利用一个处理单元和其他外部设备结合起来。并行处理与多处理系统&#xff1a;将两个以上的处理机连接起来&#xff0c;彼此进行通信协调&#xff0c;以便共同求解一个大问题的…

Spring Boot 3新特性@RSocketExchange轻松实现消息实时推送

Spring Boot 3新特性RSocketExchange轻松实现消息实时推送 随着微服务架构的普及&#xff0c;实时消息推送成为许多现代应用程序的核心需求。Spring Boot 3引入了RSocketExchange注解&#xff0c;这一新特性使得开发者能够轻松实现消息实时推送&#xff0c;极大地简化了客户端…

【Linux驱动开发】嵌入式Linux驱动开发基本步骤,字符驱动和新字符驱动开发入门,点亮LED

【Linux驱动开发】嵌入式Linux驱动开发基本步骤&#xff0c;字符驱动和新字符驱动开发入门&#xff0c;点亮LED 文章目录 开发环境驱动文件编译驱动安装驱动自动创建设备节点文件 驱动开发驱动设备号地址映射&#xff0c;虚拟内存和硬件内存地址字符驱动旧字符驱动新字符驱动 …

live2d 实时虚拟数字人形象页面显示,对接大模型

live2dSpeek 测试不用gpu可以正常运行 https://github.com/lyz1810/live2dSpeek 运行的话还需要额外下载https://github.com/lyz1810/edge-tts支持语音 ## 运行live2dSpeek >npm install -g http-server >http-server . ## 运行edge-tts python edge-tts.py

Shell实战之chmod权限讲解

目录 引言chmod命令基础权限的数字表示法权限的符号表示法特殊权限位递归修改权限实战示例常见问题与解答最佳实践与安全考虑总结 引言 在Unix和Linux系统中,文件权限管理是系统安全和用户访问控制的核心。chmod&#xff08;change mode&#xff09;命令是Shell脚本中最常用…

使用 Helsinki-NLP 中英文翻译本地部署 - python 实现

通过 Helsinki-NLP 本地部署中英文翻译功能。该开源模型性价比相对高&#xff0c;资源占用少&#xff0c;对于翻译要求不高的应用场景可以使用&#xff0c;比如单词&#xff0c;简单句式的中英文翻译。 该示例使用的模型下载地址&#xff1a;【免费】Helsinki-NLP中英文翻译本…

心觉:激活潜意识财富密码:每天一练,财富自动来

Hi&#xff0c;我是心觉&#xff0c;与你一起玩转潜意识、脑波音乐和吸引力法则&#xff0c;轻松掌控自己的人生&#xff01; 挑战每日一省写作200/1000天 为什么有些人总是轻而易举地吸引到财富 而你却努力多年仍然徘徊在财务的困境中&#xff1f; 你每天都在辛苦工作&…

MambaVision原理和源码调测

Hatamizadeh, Ali and Jan Kautz. “MambaVision: A Hybrid Mamba-Transformer Vision Backbone.” ArXiv abs/2407.08083 (2024): n. pag. 1.模型原理 关键思路&#xff1a; 通过重新设计Mamba的架构和在最终层增加自注意力块&#xff0c;提高了Mamba模型对视觉特征的建模能力…

爬虫学习实战

1.大学排名爬取&#xff08;简单&#xff09; selenium实现爬取。 # -*- coding: utf-8 -*- from selenium import webdriver from selenium.webdriver.common.by import By import timeurl https://daxue.911cha.com/ driver webdriver.Chrome() # 设置隐式等待&#xff0c;…

专题:贪心算法(已完结)

1.分发饼干 方法一&#xff1a;用最大的胃口 找到最大的饼干&#xff08;先遍历胃口&#xff09; class Solution { public:int findContentChildren(vector<int>& g, vector<int>& s) {// 主要思路 用最大的饼干找最大的胃口sort(g.begin(),g.end());so…

C语言练习

题目&#xff1a; 1.运用switch选择语句&#xff0c;编写一段C语言&#xff0c;请根据输入的数字&#xff0c;显示相应的星期日&#xff0c;如果数字所对应的星期日并不存在请显示“抱歉&#xff0c;您输入的内容并不存在。” 分析&#xff1a;1.在本题中&#xff0c;要运用到…

大厂面试真题-说一下推和拉的模式以及常见的使用

Pull&#xff08;拉&#xff09;模式和Push&#xff08;推&#xff09;模式是消息传递中的两种基本机制&#xff0c;它们在消息中间件和注册中心中的应用广泛而多样。 Pull&#xff08;拉&#xff09;模式 Pull模式是一种消息消费模式&#xff0c;其中客户端主动从服务端拉取…

C语言之扫雷小游戏(完整代码版)

说起扫雷游戏&#xff0c;这应该是很多人童年的回忆吧&#xff0c;中小学电脑课最常玩的必有扫雷游戏&#xff0c;那么大家知道它是如何开发出来的吗&#xff0c;扫雷游戏背后的原理是什么呢&#xff1f;今天就让我们一探究竟&#xff01; 扫雷游戏介绍 如下图&#xff0c;简…

【网络安全】漏洞案例:提升 Self-XSS 危害

未经许可,不得转载。 文章目录 Self-XSS-1Self-XSS-2Self-XSS-1 目标应用程序为某在线商店,在其注册页面的First Name字段中注入XSS Payload: 注册成功,但当我尝试登录我的帐户时,我得到了403 Forbidden,即无法登录我的帐户。 我很好奇为什么我无法登录我的帐户,所以我…

如何破解 AI 聊天机器人让它们吐露秘密!窥探 AI 系统指令的 10 种技巧

​ 有时&#xff0c;为了确保 AI 的安全性和透明性&#xff0c;用户需要自己动手&#xff0c;揭开系统指令的面纱。 如果人工智能现在已经成为生活中的事实&#xff0c;并影响着我们的福祉&#xff0c;人们理应知道它的运作原理。 对一些人来说&#xff0c;科幻电影中的经典…

mysql的表锁和行锁

区别&#xff1a;有索引的时候就是行锁&#xff0c;没有索引的时候就是表锁 InnoDB行锁是通过索引上的索引项来实现的&#xff0c;这一点&#xff2d;ySQL与Oracle不同&#xff0c;后者是通过在数据中对相应数据行加锁来实现的 表锁和行锁的使用场景 对于InnoDB表&#xff0…

新装ubuntu22.04必做两件事,不然可能没法用

一、换服务源 在全部里面找到软件和安装&#xff1b;打开后 在更多里面匹配一下最适合自己的软件源&#xff1b;这个过程比较漫长&#xff1b;要耐心等待 二、换软件安装中心 先执行&#xff1a; sudo apt upgrade 后执行&#xff1a; sudo apt install plasma-discover…

HBASE介绍和使用

一、HBase 简介 HBase 是一个开源的、分布式的、面向列的非关系型数据库&#xff0c;它构建在 Hadoop 文件系统&#xff08;HDFS&#xff09;之上&#xff0c;为大数据存储和处理提供了高可靠性、高可扩展性和高性能的解决方案。 二、主要特点 分布式架构 HBase 采用主从架构…