首页 > 数据库 >使用Redis实现游戏排行榜

使用Redis实现游戏排行榜

时间:2024-04-27 17:12:43浏览次数:27  
标签:游戏 level Redis rank 玩家 排行榜 key

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

1 Redis的有序集合

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

(关于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\)(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 的解决方案》)。

标签:游戏,level,Redis,rank,玩家,排行榜,key
From: https://www.cnblogs.com/lcc9527/p/18162252

相关文章

  • Installation requirements for SAP Kernels on Windows (C++ runtime environment, V
      Symptom在Windows执行StartSAP,报错信息找不到指定的模块:"Theprogramcan'tstartbecausemsvcr100.dllismissingfromyourcomputer.""无法启动此程序,因为计算机中丢失了msvcr100.dll。尝试重新安装该程序以解决此问题。" OtherTermsC,C++,runtime,VCred......
  • vmware中安装centos7, 安装redis, 并通过可视化软件(RESP)连接
    1.虚拟机网络问题解决刚安好的centos可能没有网卡(输入ipa没有ip地址),此时需要进行如下操作 vi/etc/sysconfig/network-scripts/ifconfig-ens33修改成如下:ONBOOT=yes 然后重启网络服务:servicenetworkrestart此时重新查看ipa就可以看到ip地址了在本地ping虚拟机......
  • 有意思!一个关于 Spring 历史的在线小游戏
    发现SpringOne的官网上有个好玩的彩蛋,分享给大家!进到SpringOne的官网,可以看到右下角有个类似马里奥游戏中的金币图标。点击该金币之后,会打开一个新的页面,进入下面这样一个名为:TheHistoryOfSpring的在线小游戏你可以使用上下左右的方向键来控制Spring的Logo一步步经历......
  • redis面试题
    redis面试题Redis是什么,应用场景:Redis是一种开源、内存中的数据存储系统,也被称为数据结构服务器。它支持多种数据结构(如字符串、哈希、列表、集合、有序集合、Bitmaps、HyperLogLogs等),并提供持久化、复制、事务、Lua脚本等功能。Redis常用于缓存、实时排行榜、计数器、消息队列......
  • Redis的数据持久化机制
    Redis的数据持久化机制Redis是一个高性能的内存数据库,为了保证数据的安全性,它提供了两种数据持久化机制:RDB和AOF。RDB(RedisDataBase):RDB是一种快照式的持久化方式,它会在指定的时间间隔内将内存中的数据生成一个快照文件,保存到磁盘上。当Redis重启时,可以通过加载RDB文件来恢复数......
  • JHMG游戏引擎
    ✅JHMG游戏引擎JHMG游戏引擎是我写的一个简单的2D游戏引擎,旨在帮助快速搭建和开发2D游戏。源仓库地址https://github.com/jeanhua/JHMG-enginegitee镜像地址https://gitee.com/jeanhua/JHMG-engine特点提供了游戏场景管理、游戏对象管理、界面显示、音效播放、用户输入......
  • SSRF打redis主从(更了)
    翻下去看更新受不了了。打的题目是网鼎杯2020玄武组的SSRFMe。打了一天,都是在moduleload那里失败,开了vps也不行,难道是redis版本对不上? 话不多说,我直接上payload,实在受不了了。[[email protected]]#redis-serverredis.conf[root@EddieMurphyredis-rogue-s......
  • [游戏]深岩银河幸存者 --修改实现无敌
    深岩银河幸存者--修改实现无敌目录深岩银河幸存者--修改实现无敌Il2CppDumperGameAssembly.dll/Assembly-CSharp.dll分析12345修改实现无敌global-metadata.dat未加密,直接上Il2CppDumperIl2CppDumperInitializingmetadata...MetadataVersion:29Initializingil2cp......
  • redis分布锁
     配置Redisson连接在SpringBoot项目的配置文件application.yml中添加Redisson配置:spring:data:redis:host:localhostport:6379database:0redisson:codec:org.redisson.codec.JsonJacksonCodecsingle-server-config:ad......
  • springboot链接redis IPV6
    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><exclusions><exclusion>......