本文摘自PHP中文网,作者齐天大圣,侵删。
redis里有一种很特殊的数据类型――有序集合。之前我们学过的集合的概念是,集合里所有元素都是唯一的、无序的。但这里怎么出现了有序集合,他是怎么来实现有序的呢?有序集合里元素还是唯一的,但会给每个元素设置一个socre(分值),通过这个分值来实现有序的。如下图所示:

有序集合API
下面介绍几个有序集合的API,实现排行榜功能需要知道这些API的用法。
zAdd
我们想设置一个球员2k能力值的有序列表,使用球员名为元素,能力值为scores。
库里的投射能力为100,詹姆斯为92,哈登为96,保罗为97
sadd一次可以添加1个或多个元素
1 2 3 4 | 127.0.0.1:6379[1]> zadd 2kplayer:shoot 100 curry
(integer) 1
127.0.0.1:6379[1]> zadd 2kplayer:shoot 92 james 96 harden 97 paul
(integer) 3
|
zIncrBy
这一个月来,哈登连续爆种,疯狂连续砍高分,那么,2k决定将他的投射能力值提高2点
1 2 | 127.0.0.1:6379[1]> zincrby 2kplayer:shoot 2 harden
"98"
|
zRange、zRevRange
现在我们想知道能力值前3名的球员是哪3个。
1 2 3 4 5 6 7 | 127.0.0.1:6379[1]> zrange 2kplayer:shoot 0 2 withscores
1) "james"
2) "92"
3) "paul"
4) "97"
5) "harden"
6) "98"
|
redis默认采用正序,分值从小到大排序。所以我们需要使用zRevRange
1 2 3 4 5 6 7 | 127.0.0.1:6379[1]> zrevrange 2kplayer:shoot 0 2 withscores
1) "curry"
2) "100"
3) "harden"
4) "98"
5) "paul"
6) "97"
|
zUnionStore
2k能力值是有多方面的,投射只是其中一项,速度、上篮等都是能力值的一部分。
1 2 | 127.0.0.1:6379[1]> zadd 2kplayer:speed 99 james 90 paul 90 curry 93 harden
(integer) 4
|
这时候,想知道球员综合能力值的话,就需要将每一项的得分都加起来
1 2 3 4 5 6 7 8 9 10 11 | 127.0.0.1:6379[1]> zunionstore 2kplayer 2 2kplayer:shoot 2kplayer:speed
(integer) 4
127.0.0.1:6379[1]> zrange 2kplayer 0 -1 withscores
1) "paul"
2) "187"
3) "curry"
4) "190"
5) "harden"
6) "191"
7) "james"
8) "191"
|
实现排行榜系统
场景如下:一个视频点播系统,每天观看的人很多。该系统有个榜单功能,展示观看量最多的视频。分为今日榜单、三日榜单、一周排行、月榜单。
思路:首先是按天统计视频观看次数,然后再统计出今日榜单、三日榜单等。
统计视频观看次数的伪代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 | function view ( $videoId )
{
$key = 'video:view:' . date ( 'Y-m-d' );
if (! $redis ->exists( $key )) {
$redis ->zIncrBy( $key , 1, $videoId );
$redis ->expire( $key , 86400 * 30);
}
$redis ->zIncrBy( $key , 1, $videoId );
}
|
今日最热
今日最热有一个注意点,当新的一天刚开始时,数据可能为空或很少。所以,我们可以将今日和昨日的数据合并起来,但将今日的数据权重设高些。
今日最热功能实现伪代码如下:
1 2 3 4 5 6 7 8 9 10 | function todayHot ()
{
$tokeyKey = 'video:view:' . date ( 'Y_m_d' );
$yesKey = 'video:view:' . date ( 'Y_m_d' , time() - 86400);
$keyUnion = "view:rank:today" ;
$redis ->zUnionStore( $keyUnion , [ $tokeyKey , $yesKey ], [10, 1]);
return $redis ->zRevRange( $keyUnion , 0, 99);
}
|
三日榜单
1 2 3 4 5 6 7 8 9 10 11 12 | function threeHot ()
{
$keyUnion = 'view:rank:three' ;
$unionKeys = [];
for ( $i =0; $i < 3; $i ++) {
$unionKeys [] = 'video:view:' . date ( 'Y_m_d' , time() - 86400 * $i );
}
$redis ->zUnionStore( $keyUnion , $unionKeys );
return $redis ->zRevRange( $keyUnion , 0, 99, true);
}
|
周榜单、月榜单等和三日榜单的思路完成一样,所以就不贴出代码了。
以上就是使用Redis完成排行榜系统的详细内容,更多文章请关注木庄网络博客!
相关阅读 >>
Redis中两种持久化缺陷介绍
Redis和session的区别
Redis是什么意思?
Redis实现限速器的几种方式
为什么需要Redis
Redis介绍分布式数据库cap原理
Redis怎么实现分布式事务
使用Redis完成微信摇一摇功能
Redis缓存策略哪几种
为什么Redis是单线程、及高并发快原因详解
更多相关阅读请进入《Redis》频道 >>
机械工业出版社
本书主要讲述了数据模型、基于对象的数据库和XML、数据存储和查询、事务管理、体系结构等方面的内容。
转载请注明出处:木庄网络博客 » 使用Redis完成排行榜系统