php 实时更新内容_PHP+Redis 有序集合实现 24 小时排行榜实时更新
php中文网最新课程
每日17点准时技术干货分享
基本介绍
Redis 有序集合和集合一样也是 string 类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。
有序集合的成员是唯一的,但分数 (score) 却可以重复。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O (1)。集合中最大的成员数为 2^32 - 1^ (4294967295, 每个集合可存储 40 多亿个成员)。
有序集合首先是集合,其成员(member)具有唯一性,其次,每个成员关联了一个分数(score),使得成员可以按照分数排序。
需求描述
设想在一个游戏中,有上百万的玩家数据,如果现在需要你根据玩家的经验值整理一个前 10 名的排行榜,你会怎么做呢?一般的做法是写一条类似下面这条 sql 语句的方式来获取:
select * from game_socre order by score desc limit 0,20
这种方式在数据量较小的情况下可行,但是在数据量大的情况下查询速度将变慢,特别是还需要联表查询时,速度下降的就更明显了。
实现
这时你可以考虑使用 redis 来实现这个功能。
实现这个功能主要用到的 redis 数据类型是 redis 的有序集合 zset。zset 是 set 类型的一个扩展,比原有的类型多了一个顺序属性。此属性在每次插入数据时会自动调整顺序值,保证 value 值按照一定顺序连续排列。
主要的实现思路是:
1、在一个新的玩家参与到游戏中时,在 redis 中的 zset 中新增一条记录(记录内容看具体的需求)score 为 0
2、当玩家的经验值发生变化时,修改该玩家的 score 值
3、使用 redis 的 ZREVRANGE 方法获取排行榜
返回有序集 key 中,指定区间内的成员。其中成员的位置按 score 值递减 (从大到小) 来排列。具有相同 score 值的成员按字典序的反序排列。除了成员按 score 值递减的次序排列这一点外,ZREVRANGE 命令的其他方面和 ZRANGE 命令一样。
redis 127.0.0.1:6379> ZADD KEY_NAME SCORE1 VALUE1.. SCOREN VALUEN
1、数据准备
2、获取 score 高分 top10 排名 (ZREVRANGE 为降序,ZRANGE 为升序)
3、查看用户 ee 的实际排名 (ZREVRANK 为降序,ZRANK 为升序)、实时分数
进一步需求
需要实现最近的 24 小时用户积分排行榜,并统计前 10 名的玩家和积分
实现
主要的实现思路是:
利用 ZADD 按小时划分添加用户的积分信息,然后用 ZUNIONSTORE 并集实现 24 小时的游戏积分总和,实现 “24 小时排行榜”;(如果有更好的思路,能够在下方留言不吝赐教一下就更好了)
ZUNIONSTORE destination numkeys key [key ...]
Redis Zunionstore 命令计算给定的一个或多个有序集的并集,其中给定 key 的数量必须以 numkeys 参数指定,并 将该并集(结果集)储存到 destination 。
默认情况下,结果集中某个成员的分数值是所有给定集下该成员分数值之和 。
可能碰到的问题
1、相同分数问题
Redis 在遇到分数相同时是按照集合成员自身的字典顺序来排序,这里即是按照”user2″和”user3″这两个字符串进行排序,以逆序排序的话 user3 自然排到了前面。要解决这个问题,我们可以考虑在分数中加入时间戳,计算公式为:
带时间戳的分数 = 实际分数*10000000000 + (9999999999 – timestamp)
timestamp 我们采用系统提供的 time () 函数,也就是 1970 年 1 月 1 日以来的秒数,我们采用 32 位的时间戳(这能坚持到 2038 年),由于 32 位时间戳是 10 位十进制整数(最大值 4294967295);
所以我们让时间戳占据低 10 位(十进制整数),实际分数则扩大 10^10 倍,然后把两部分相加的结果作为 zset 的分数。考虑到要按时间倒序排列,所以时间戳这部分需要颠倒一下,这便是用 9999999999 减去时间戳的原因。
当我们要读取玩家实际分数时,只需去掉后 10 位即可。
初步看起来这个方案还不错,但这里面有两个问题。
第一个问题是小问题,采用秒为时间戳可能区分度还不够,如果同一秒出现两个分数相同的仍然会出现前面的问题,当然我们可以选择精度更高的时间戳,但在实际场景中,同一秒谁排前面已经无关紧要。
第二个问题是大问题,因为 Redis 的分数类型采用的是 double,64 位双精度浮点数只有 52 位有效数字,它能精确表达的整数范围为 - 2^53 到 2^53,最高只能表示 16 位十进制整数(最大值为 9007199254740992,其实连 16 位也不能完整表示)。
这就是说,如果前面时间戳占了 10 位的话,分数就只剩下 6 位了,这对于某些排行榜分数来说是不够用的。我们可以考虑缩减时间戳位数,比如从 2015 年 1 月 1 日开始计时,但这仍然增加不了几位。
或者减少区分度,以分钟、小时来作为时间戳单位。
如果 Redis 的分数类型为 int64,我们就没有上面的烦恼。
说到这里,其实 Redis 真应该再额外提供一个 int64 类型的 ZSet,但目前只能是幻想,除非自己改其源码。
-END-
▼
php 实时更新内容_PHP+Redis 有序集合实现 24 小时排行榜实时更新相关推荐
- php数值相加_PHP+Redis 有序集合实现 24 小时排行榜实时更新
php中文网最新课程 每日17点准时技术干货分享 基本介绍 Redis 有序集合和集合一样也是 string 类型元素的集合,且不允许重复的成员. 不同的是每个元素都会关联一个 double 类型的分 ...
- 实时用户在线人数统计(二):redis有序集合
可以用Redis的有序集合存储用户信息,来实现实时在线人数统计. 注:以下只为设计思路,代码均为模拟代码,不可作为正式项目使用.代码使用的laravel框架. redis有序集合实现在线人数统计 // ...
- Redis 命令--Redis有序集合(sorted set)
Redis有序集合(sorted set) Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员. 不同的是每个元素都会关联一个double类型的分数.redis正是通过分 ...
- php redis 搜索,PHP+Redis有序集合(zset)实现博客园阅读排行榜功能
许多网站都有排行榜的功能,比如球员人气榜单.阅读排行榜,对于一些小网站,通过查数据库就能实现排行榜的功能,但是对于稍微有点用户量而且还是实时排名的网站,使用一些关系型数据库如(MySQL.Oracle ...
- Redis学习---(11)Redis 有序集合(sorted set)
Redis 有序集合(sorted set) Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员. 不同的是每个元素都会关联一个double类型的分数.redis正是通过 ...
- 每个选项设置上限的投票_使用Redis有序集合实现投票排行榜系统
需求 业务开发中多多少少会遇到这种需求,需要一个排行榜,它需要对列表中成员的票数进行排序. 在一个排行榜中,成员的名次是要根据当前票数动态变化的,如果使用Mysql,将会造成频繁的修改,Mysql的性 ...
- php redis sorted set,Redis 有序集合(sorted set)
Redis 有序集合(sorted set) Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员. 不同的是每个元素都会关联一个double类型的分数.redis正是通过 ...
- Redis有序集合(sorted set)使用
有序集合说明 Redis的有序集合(sorted set),同时具有"有序"和"集合"两种性质,这种数据结构中的每个元素都由一个成员和和一个与成员相关联的分值组 ...
- redis有序集合zset详解
zset 概述 Redis有序集合zset与普通集合set非常相似,是一个没有重复元素的字符串集合. 不同之处是有序集合的每个成员都关联了一个评分(score),这个评分(score)被用来按照从最低 ...
最新文章
- 1047.删除字符串中的所有相邻重复项
- IBM Bluemix体验:Containers持久存储
- VBS常用函数及功能
- 配置 --- 将本地项目部署到阿里云上
- varnish 高性能方向代理服务器
- 魅族android n内测报名,底层升级安卓 N 内测报名 Flyme 迎来五周年
- ssm项目之sql查询的问题
- oracle 创建一个用户,只能访问指定的对象
- linux开发屏幕保护代码,使用xscreensaver编写屏幕保护程序的提示和技巧?
- .net 开源混淆器 ConfuserEx
- DeepMind再登Nature封面!2000年前残断古希腊文,完形填空七成准
- 英语计算机四级成绩查询入口,全国计算机四级考试成绩查询入口
- 论文笔记: 多标签学习 PML-NI 算法
- 从青蒿素说一下专利与知识产权[更新]
- python空格隔开输入
- 给苹果电脑选机械键盘
- Java接口中的方法和常量
- linux下载安装tree命令
- B2092 开关灯 【入门】
- java毕业设计_基于web的医院信息管理系统
热门文章
- GitHub#C#:在终端里面显示一个UI窗口(TerminalGfx)
- python模块化编程_什么是模块,Python模块化编程(入门必读)
- SpringCloud概念理解
- 大数据城市规划 杨东_AI为智慧城市规划做建设
- 在python中可以使用if作为变量名_变量,注释,缩进,细数Python优雅风 | Python基础连载(二)...
- linux减小根目录空间_Linux目录结构及文件基本操作详解
- 简单python代码实例_求简洁优美的python代码例子、片段、参考资料
- java,如何处理大批量数据插入
- Docker简单实践(一)
- Unity2020.1新功能探路:图形渲染相关更新