有序集合里元素还是唯一的,但会给每个元素设置一个socre(分值),通过这个分值来实现有序的。如下图所示:
有序集合api
下面介绍几个有序集合的api,实现排行榜功能需要知道这些api的用法。
zadd
我们想设置一个球员2k能力值的有序列表,使用球员名为元素,能力值为scores。
库里的投射能力为100,詹姆斯为92,哈登为96,保罗为97
sadd一次可以添加1个或多个元素
127.0.0.1:6379[1]> zadd 2kplayer:shoot 100 curry(integer) 1127.0.0.1:6379[1]> zadd 2kplayer:shoot 92 james 96 harden 97 paul(integer) 3
zincrby
这一个月来,哈登连续爆种,疯狂连续砍高分,那么,2k决定将他的投射能力值提高2点
127.0.0.1:6379[1]> zincrby 2kplayer:shoot 2 harden"98"
zrange、zrevrange
现在我们想知道能力值前3名的球员是哪3个。
127.0.0.1:6379[1]> zrange 2kplayer:shoot 0 2 withscores1) "james"2) "92"3) "paul"4) "97"5) "harden"6) "98"
redis默认采用正序,分值从小到大排序。所以我们需要使用zrevrange
127.0.0.1:6379[1]> zrevrange 2kplayer:shoot 0 2 withscores1) "curry"2) "100"3) "harden"4) "98"5) "paul"6) "97"
zunionstore
2k能力值是有多方面的,投射只是其中一项,速度、上篮等都是能力值的一部分。
127.0.0.1:6379[1]> zadd 2kplayer:speed 99 james 90 paul 90 curry 93 harden (integer) 4
这时候,想知道球员综合能力值的话,就需要将每一项的得分都加起来
127.0.0.1:6379[1]> zunionstore 2kplayer 2 2kplayer:shoot 2kplayer:speed(integer) 4127.0.0.1:6379[1]> zrange 2kplayer 0 -1 withscores1) "paul"2) "187"3) "curry"4) "190"5) "harden"6) "191"7) "james"8) "191"
实现排行榜系统
场景如下:一个视频点播系统,每天观看的人很多。该系统有个榜单功能,展示观看量最多的视频。分为今日榜单、三日榜单、一周排行、月榜单。
思路:首先是按天统计视频观看次数,然后再统计出今日榜单、三日榜单等。
统计视频观看次数的伪代码如下:
// 观看视频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);}
今日最热
今日最热有一个注意点,当新的一天刚开始时,数据可能为空或很少。所以,我们可以将今日和昨日的数据合并起来,但将今日的数据权重设高些。
今日最热功能实现伪代码如下:
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]); // 取前100名 return $redis->zrevrange($keyunion, 0, 99);}
三日榜单
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完成排行榜系统的详细内容。
