SQL 必知必会
陈旸
清华大学计算机博士
73338 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 50 讲
第一章:SQL语法基础篇 (19讲)
SQL 必知必会
15
15
1.0x
00:00/00:00
登录|注册

43丨如何使用Redis搭建玩家排行榜?

增加或删除某个玩家,并对排名进行更新
查询指定玩家前后M名的玩家
对玩家的分数进行更新,同时排名进行更新
查询某个玩家的排名
查询某个玩家的分数
按名次查询排名前N名的玩家
统计全部玩家的排行榜
使用Lua创建10万名玩家数据
如何在Redis中使用Lua
使用存储过程模拟10万名玩家数据
王者荣耀英雄等级说明
调整排名规则的编写
Lua脚本模拟10万名玩家的数据
Redis对排行榜的优势
使用Redis实现玩家排行榜
Lua是什么,如何在Redis中使用
使用MySQL搭建玩家排行榜
总结
如何使用Redis搭建玩家排行榜?

该思维导图由 AI 生成,仅供参考

上一篇文章中,我们使用 Redis 模拟了多用户抢票的问题,这里再回顾一下原理。我们通过使用 WATCH+MULTI 的方式实现乐观锁机制,对 ticket_count 这个键进行监视,当这个键发生变化的时候事务就会被打断,重新请求,这样做的好处就是可以保证事务对键进行操作的原子性,当然我们也可以使用 Redis 的 incr 和 decr 来实现键的原子性递增或递减。
今天我们用 Redis 搭建一个玩家的排行榜,假设一个服务器存储了 10 万名玩家的数据,我们想给这个区(这台服务器)上的玩家做个全区的排名,该如何用 Redis 实现呢?
不妨一起来思考下面几个问题:
MySQL 是如何实现玩家排行榜的?有哪些难题需要解决?
如何用 Redis 模拟 10 万名玩家数据?Redis 里的 Lua 又是什么?
Redis 如何搭建玩家排行榜?和 MySQL 相比有什么优势?

使用 MySQL 搭建玩家排行榜

我们如果用 MySQL 搭建玩家排行榜的话,首先需要生成 10 万名玩家的数据,这里我们使用之前学习过的存储过程来模拟。
为了简化,玩家排行榜主要包括 3 个字段:user_id、score、和 create_time,它们分别代表玩家的用户 ID、玩家的积分和玩家的创建时间。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Redis排行榜搭建及Lua脚本应用 本文介绍了如何使用Redis搭建玩家排行榜,并重点介绍了如何在Redis中使用Lua脚本来实现类似存储过程的功能。通过模拟生成10万名玩家数据,并将其存储在Redis的有序集合中,文章详细讨论了Redis在实现玩家排行榜功能上的优势。通过对Redis提供的命令格式和功能实现,包括统计全部玩家的排行榜、按名次查询排名前N名的玩家、查询某个玩家的分数和排名、对玩家的分数和排名进行更新、查询指定玩家前后M名的玩家以及增加或删除某个玩家并对排名进行更新等功能的实现方法。文章还强调了Redis集成了Lua脚本语言,通过Lua可以更加灵活地扩展Redis的功能,并对Redis中使用Lua语言的优势进行了介绍。总结了Redis在实时更新排行榜、提供丰富的排行榜统计功能以及对Lua脚本的灵活应用等方面的优势。整体内容涉及技术性较强,适合对Redis和MySQL有一定了解的读者阅读。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《SQL 必知必会》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(7)

  • 最新
  • 精选
  • 石维康
    在生成数据时,把"temp = temp + create_time / 10000000000"换成 temp = temp +1 - create_time / 10000000000 哈哈

    作者回复: 不错的方法 哈哈

    2019-09-12
    3
    11
  • Demon.Lee
    感觉用redis,最终还是需要结合程序以及MySQL来处理,因为排行榜展示,前端还是需要用户名的,光给个用户id不知道是谁,除非redis有序集合的member包含了用户id和name,请指正。

    作者回复: 通常一个功能用一种DBMS即可,所以会用到有序集合的member保存id和name。因为这些数据是需要高频访问的,所以放到redis中会更适合。如果想要查询更具体的数据,需要用户点击排行榜中的某个玩家的时候,可以使用MySQL来处理,比如查看这个玩家具体使用过哪些英雄,具体战绩如何等。

    2019-09-12
    5
    11
  • JustDoDT
    注册时间排名靠后MySQL语法:create_time按照降序排列。 SELECT (@rownum := @rownum + 1) AS user_rank, user_id, score, create_time FROM user_score, (SELECT @rownum := 0) b ORDER BY score DESC, create_time DESC

    作者回复: Good Job

    2019-09-11
    5
  • 博弈
    Redis在实现排行榜方面优势显著,有现成命令且在内存操作,速度快

    作者回复: 对的

    2020-03-27
    3
  • felix
    咨询老师一个关于ip匹配的索引问题: 有一个IP的库表,每一条记录了一个开始ip和结束ip,然后想批量匹配ip,查询为何没有用上“联合索引KEY `ip_range_int` (`start_int`,`end_int`) USING BTREE”?要怎么设置索引才有效? CREATE TABLE `t_dt_ip` ( `id` int(11) NOT NULL AUTO_INCREMENT, `start_ip` char(15) DEFAULT NULL, `end_ip` char(15) DEFAULT NULL, `location` varchar(100) DEFAULT NULL, `start_int` int(10) unsigned DEFAULT '0', `end_int` int(10) unsigned DEFAULT '0', PRIMARY KEY (`id`), KEY `ip_range` (`start_ip`,`end_ip`) USING BTREE, KEY `ip_range_int` (`start_int`,`end_int`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; explain update t_tmp_ip t, t_dt_ip i set t.ip_id = i.id where INET_ATON(t.ip_address) between i.start_int and i.end_int; | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | | 1 | UPDATE | t | NULL | ALL | NULL | NULL | NULL | NULL | 1000 | 100.00 | NULL | | 1 | SIMPLE | i | NULL | ALL | ip_range_int | NULL | NULL | NULL | 541942 | 11.11 | Range checked for each record (index map: 0xC) | 甚至加上单个字段索引也没有用?? alter table `t_dt_ip` add index indx_t_dt_ip_start_int (start_int); mysql> explain select * from t_dt_ip i join t_tmp_ip t on 1= 1 where t.ip_address >= i.start_int limit 1; | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | | 1 | SIMPLE | t | NULL | ALL | NULL | NULL | NULL | NULL | 73126 | 100.00 | NULL | | 1 | SIMPLE | i | NULL | ALL | ip_range_int,indx_t_dt_ip_start_int | NULL | NULL | NULL | 541942 | 33.33 | Range checked for each record (index map: 0xC) |

    作者回复: 感谢提问,where INET_ATON(t.ip_address) between i.start_int and i.end_int 这里会对i.start_int 和 i.end_int进行比较。所以如果设置了联合索引KEY `ip_range_int` (`start_int`,`end_int`) USING BTREE 是不会起作用的,因为联合索引具有最左匹配原则 下面 add index indx_t_dt_ip_start_int (start_int),说明对单个字段start_int 创建了index,所以在possible_keys 中存在start_int。具体是否需要索引MySQL还是会根据实际情况来判断,因为每次比较是判断where t.ip_address >= i.start_int 这里会和根据t.ip_address以及i.start_int的数据分布情况而定,如果MySQL认为这需要扫描大部分索引,因此意义不大时就不会采用索引字段start_int

    2019-09-14
    2
  • 白菜炒五花肉
    ERR Error running script (call to f_84b63a152215a96efa70b8935ae3d2b0e5ab93d1): @user_script:3: user_script:3: bad argument #1 to 'randomseed' (number expected, got nil) 老师,使用redis创建10w名玩家数据,执行lua脚本,报这个错误是啥问题
    2022-08-25归属地:上海
  • 完美坚持
    为什么 查询某个玩家的排名 对玩家的分数和排名进行更新 查询指定玩家前后 M 名的玩家 增加或移除某个玩家,并对排名进行更新 的时间复杂度都是O(log(N)),这和有序集合的数据存储结构有关吗?老师能不能简单解释一下,或者给个链接
    2021-06-09
    2
收起评论
显示
设置
留言
7
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部