使用Redis完成排行榜系统


本文摘自PHP中文网,作者齐天大圣,侵删。

redis里有一种很特殊的数据类型――有序集合。之前我们学过的集合的概念是,集合里所有元素都是唯一的、无序的。但这里怎么出现了有序集合,他是怎么来实现有序的呢?

有序集合里元素还是唯一的,但会给每个元素设置一个socre(分值),通过这个分值来实现有序的。如下图所示:

QQ截图20200514082750.png

有序集合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]);

    // 取前100名

    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》频道 >>


数据库系统概念 第6版
书籍

数据库系统概念 第6版

机械工业出版社

本书主要讲述了数据模型、基于对象的数据库和XML、数据存储和查询、事务管理、体系结构等方面的内容。



打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...