使用Redis实现游戏排行榜

排行榜在当今应用中扮演着至关重要的角色。无论是游戏中的玩家排名、社交平台的用户活跃度榜单,还是其他领域的各种榜单,排行榜都是用户参与性和互动性的关键。在实现排行榜功能时,选择合适的数据库和数据结构至关重要。Redis,作为一种内存数据库,以其高性能和灵活性而备受青睐。下面将探讨如何使用Redis的有序集合(Sorted Set)来实现排行榜功能。

1 Redis的有序集合

Redis是一种内存型数据库,查询效率高。Redis有一种数据结构叫有序集合(Sorted Set),与普通集合相比,它的每个成员都关联一个分数,这个分数用于对成员进行排序。有序集合在插入和查询时都能够以 O ( l o g n ) O(log{n}) O(logn)的复杂度完成,这为排行榜的实现提供了高效的基础。有序集合不仅提供了快速的插入和查询操作,还支持范围查询,使得获取某个范围内的排名成员变得非常简单。

(关于Sorted Set如何实现高效的插入和查询,可以看我的这篇文章《Redis的跳跃表》)

2 使用有序集合实现排行榜

那么,我们要如何用Sorted Set来实现排行榜呢?

其实非常简单,首先根据需求,我们定义一个有序集合的key,例如:

  • 玩家等级的排行榜,我们可以用rank:level来作key值。
  • 每天更新的排行榜,可以在后面加个日期rank:level:0412
  • 还有些比如是每天对指定BOSS的伤害排行,可以用rank:damage:bossID:0412

当排行数值改变的时候,我们用zadd指令来更新数据:

zadd rank:level 玩家等级 玩家ID #参数是`score`和`member`

也可以用

ZINCRBY rank:level 10 lxx1 #使lxx1的积分增加10(如果lxx1在rank:level中不存在,则新增,设置积分为10)

需要查询排行榜数据的时候,我们用zrevrange指令来获取数据(下标是从0开始):

zrevrange rank:level 0 99 WITHSCORES    # 获取前100名的ID和分数
zrevrange rank:level 100 199 WITHSCORES # 获取101-200名的ID和分数
zrevrange rank:level 0 99               # 仅获取ID

这里我们使用zrevrange,因为zset是按从小到大排序的,zrevrange是逆序返回zset中的数据。

取出玩家ID之后,我们再从另外的地方(MySQLredis或者内存中)获取玩家的其他数据(名字,头像等),组合出完整的榜单数据。

查看排行玩家的排行和数值:

zscore rank:level lxx1 #获取玩家lxx1的分数
zrevrank rank:level lxx1 #获取玩家lxx1的排名

如果要移除某个玩家的排行,可以使用zrem指令:

zrem rank:level 玩家ID

3 实现数值相同时,按时间先后排序

游戏排行榜中,经常有这样的需求:玩家等级相同时,按照到达这个等级的时间先后顺序排序。

使用Sorted Set时,我们可以将数值乘以一个系数,然后加上时间戳来实现这个功能。

比如,玩家等级27级,当前时间戳是1705589522,我们可以将这两个数组组合起来,由于时间戳是越小排序越前(和等级越大排序越前相反),我们使用相减的方式:

val = 27*1e10 + 1e10 - 1705589522

最终的结果是278294410478,其中前面的27表示等级,后面的8294410478是时间戳和1e10的差值(10位数的时间戳最大可以用到2086年,有生之年够用了),等级越大,这个值越大,而等级相同时,时间戳小的值更大。

值得注意的是,Sorted Set底层是使用double类型来存储数值,所以当排序的值过大时,加上这个时间戳可能就会不够精细。

通常来说,使用double能表示的精确的正整数可以达到 2 53 − 1 {2}^{53}-1 2531(900719925474099116位数字)(关于这个值的计算,可以看我的另一篇文章《double 类型中可精确表达的最大正整数》)

不过对于排行榜而言,如果本身的数值已经很大了,通常也不需要按照时间来排序了。比如BOSS伤害十几亿,这时候玩家连具体数值可能都看不到,通常也不会相同,用不着时间先后排序了。

4 排行榜的合并

合服的时候,使用Sorted Set也可以很方便的合并排行榜。

Redis提供了并集(zunionstore)操作,并集指的是将两个或多个zset中的元素合并为一个新的zset

它的语法如下:

ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]

其中destination表示合并到的目标keynumkeys表示后面有多少个key要用来合并。例如有三个key需要合并:rank:s1:levelrank:s2:levelrank:s3:level,我们可以这样写:

ZUNIONSTORE rank:s1:level 3 rank:s1:level rank:s2:level rank:s3:level

表示将三个key合并,然后存储到rank:s1:level这个key中。

不过需要注意的是,在Redis的集群模式下,这样操作有可能会报错。(具体看这里《Redis 报错:CROSSSLOT Keys in request don’t hash to the same slot 的解决方案》)。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

linux系统-FTP服务配置

目录 一、FTP简介 1.什么是FTP??? 2.FTP的两种模式 二、安装配置FTP服务 1.关闭防火墙和核心防护 2.安装VSFTPD 3.修改配置文件 4.黑白名单设置 一、FTP简介 1.什么是FTP?&…

jvm中的引用类型

Java中的引用类型 1.强引用 一个对象A被局部变量、静态变量引用了就产生了强引用。因为局部变量、静态变量都是被GC Root对象关联上的,所以被引用的对象A,就在GC Root的引用链上了。只要这一层关系存在,对象A就不会被垃圾回收器回收。所以只要…

Linux---自定义协议

应用层协议 一、协议定制---以网络计算器为例 网络计算机功能---进行-*/^&|的运算并返回结果 请求和响应的结构体如下 // Protocol.hpp #pragma once #include <iostream> #include <memory> class Request { public:Request(){}Request(int data_x, int da…

无人机探测技术,无人机侦测频谱仪技术实现详解

频谱仪&#xff0c;又称为频谱分析仪&#xff0c;是一种用于测量电信号频谱特性的仪器。其基本原理是通过将时域信号转换为频域信号&#xff0c;进而分析信号的频率成分、功率分布、谐波失真等参数。频谱仪利用快速傅里叶变换&#xff08;FFT&#xff09;算法&#xff0c;将采集…

13 c++版本的五子棋

前言 呵呵 这大概是 大学里面的 c 五子棋了吧 有一些 面向对象的理解, 但是不多 这里 具体的实现 就不赘述, 仅仅是 发一下代码 以及 具体的使用 然后 貌似 放在 win10 上面执行 还有一些问题, 渲染的, 应该很好调整 五子棋 #include<Windows.h> #include<io…

安规电容定义和应用

安规电容 定义 失效后&#xff0c;不会导致电击&#xff0c;不危及人身安全的电容器&#xff0c;称之为安规电容 分类 分为X电容和Y电容 X电容–跨接在电力线&#xff08;L-N&#xff09;之间的电容&#xff0c;一般选用金属薄膜电容&#xff0c;X电容有多种颜色&#xff…

VUE3----Swiper滑动切换图片

Swiper滑动切换图片 可以切换焦点图&#xff0c;兼容小程序 <template><view class"cc-swiper-container" v-if"imageList.length > 0"><swiper class"swiper":class"swiperClassName" :circular"circular&q…

Docker常用命令(镜像、容器)

一、镜像 1.1 存出镜像 1.2 载入镜像 1.3 上传镜像 二、容器 2.1 容器创建 2.2 查看容器的运行状态 ​2.3 启动容器 2.4 创建并启动容器 2.5 在后台持续运行 docker run 创建的容器 2.6 终止容器运行 2.7 容器的进入 ​2.8把宿主机的文件传入到容器内部 2.9 从容器…

C语言 | Leetcode C语言题解之第51题N皇后

题目&#xff1a; 题解&#xff1a; int solutionsSize;char** generateBoard(int* queens, int n) {char** board (char**)malloc(sizeof(char*) * n);for (int i 0; i < n; i) {board[i] (char*)malloc(sizeof(char) * (n 1));for (int j 0; j < n; j) board[i][…

Spring Cloud学习笔记(Feigh):简介,实战简单样例

这是本人学习的总结&#xff0c;主要学习资料如下 - 马士兵教育 1、Netflix Feign简介2、Open Feign的简单样例2.1、dependency2.2、代码样例 1、Netflix Feign简介 Netfilx Feign是用来帮助发送远程服务的&#xff0c;它让开发者觉得调用远程服务就像是调用本地方法一样&…

服务器数据恢复—ESXi无法识别数据存储和VMFS文件系统如何恢复数据?

服务器数据恢复环境&#xff1a; 一台某品牌服务器&#xff0c;通过FreeNAS来做iSCSI&#xff0c;然后使用两台同品牌服务器做ESXi虚拟化系统。 FreeNAS层为UFS2文件系统&#xff0c;使用整个存储建一个稀疏模式的文件&#xff0c;挂载到ESXi虚拟化系统。ESXi虚拟化系统中有3台…

怎样通过HTTP协议实现远程控制两路开关

怎样通过HTTP协议实现远程控制两路开关呢&#xff1f; 本文描述了使用HTTP协议调用HTTP接口&#xff0c;实现控制两路开关&#xff0c;两路开关可控制两路照明、排风扇等电器。 可选用产品&#xff1a;可根据实际场景需求&#xff0c;选择对应的规格 序号设备名称厂商1智能Wi…

flutter开发实战-build apk名称及指令abiFilters常用gradle设置

flutter开发实战-build apk名称及指令abiFilters常用gradle设置 最近通过打包flutter build apk lib/main.dart --release&#xff0c;发现apk命名规则需要在build.gradle设置。这里记录一下。 一、apk命名规则 在android/app/build.gradle中需要设置 android.applicationVa…

OpenWrt上的docker容器无法访问外网解决

容器里能ping通OpenWrt的管理地址和wan口地址&#xff0c;但ping外网别的ip或域名就无法访问 简单修改设置就可以&#xff1a; Luci>网络>防火墙>转发&#xff1a;接受 ->保存应用

俩招解决vs code中文编译乱码现象

如下图所示 输出会出现乱码,引起这个情况的原因是什么呢? 本页面的编码形式可能不是 utf-8 的形式。 解决方法一 可以尝试使用命令 system("chcp 65001"); system("chcp 65001"); system("chcp 65001"); 这条命令在C程序中用于解决中文乱码问…

银行押款车远程监控系统的实际需求与特点

随着金融行业的快速发展&#xff0c;银行押款车的安全性问题日益受到重视。传统的押款车监控方式已经无法满足现代安全管理的需求&#xff0c;因此&#xff0c;一种结合先进技术的远程监控系统应运而生。本文旨在探讨在运钞车上安装车载摄像机和集成有GPS、无线4G网络传输模块的…

四数之和 ---- 双指针

题目链接 题目: 分析: 我们已经知道三数之和如何求取, 并去重了 三数之和 那么四数之和同理, 需要固定两个数a和b 然后用"双指针算法" , 只要两指针之和等于target-a-b即可同样对于四个数都要进行去重 代码: class Solution {public List<List<Integer>…

LM2576D2TR4-5G 3.0安15伏降压开关稳压器 PDF中文资料_参数_引脚图

LM2576D2TR4-5G 规格信息&#xff1a; 制造商:ON Semiconductor 产品种类:开关稳压器 RoHS:是 装置风格:SMD/SMT 封装 / 箱体:TO-263-5 输出电压:5 V 输出电流:3 A 输出端数量:1 Output 最大输入电压:45 V 拓扑结构:Buck 最小输入电压:7 V 开关频率:52 kHz 最小工作…

新书推荐机器学习大数据平台的构建、任务实现与数据治理

在大数据与机器学习日新月异的今天&#xff0c;构建稳定、安全、可扩展的数据平台已成为企业和研究机构的迫切需求。这本书应运而生&#xff0c;提供了详尽且实用的指南&#xff0c;帮助读者在云计算环境中构建、优化和治理大数据平台。 作者以清晰明了的写作风格&#xff0c;…

最小费用流相位解包裹

% test_cunwrap.m % % Matlab script to test Costantinis unwrapping % Author: Bruno Luong <brunoluong@yahoo.com> % History: % Orginal: 27-Aug-2009clear all; close all; clc; I1=double(imread(E:\zhenlmailcom-E8E745\华为家庭存储\.public_files\博士阶段\小…
最新文章