美文网首页
使用Redis实现一个排行榜功能

使用Redis实现一个排行榜功能

作者: a9b854aded01 | 来源:发表于2019-07-26 14:57 被阅读0次

该功能主要使用到Redis的有序集合(SortedSet)来实现的,主要参考的https://blog.csdn.net/pbymw8iwm/article/details/81130639
来实现这样一个功能,由于最近写的是PHP项目,所以使用PHP+predis的代码实现。

Predis 操作手册https://www.cnblogs.com/houdj/p/6859719.html

1、首先实现对每个用户增加集分的操作:
遇到问题:由于Zset提供了丰富的功能,但是不存在一个提供判断ZSet中某个键是否存在指定成员的函数,
新增一个Set中的Key方法是Zadd,增加Score的方法是Zincrby,无法给一个不存在的成员增加Score。
解决方案参考:https://blog.csdn.net/sparkexpert/article/details/78351558 使用Zrank 排名大于等于0则存在,null则不存在。

源码:

    public function rankIncrease($key,$user,$count = 1)
    {
        //var_dump($user['id']);die;
        $rediskey = $key . date('Ymd');
        try {
            //如果当天排行不存在则创建Key并设置过期时间
            if(!Redis::exists($rediskey)) {
                $value = $user['id'] . '|' . $user['name'] . '|' . $user['avatar'];
                Redis::zadd($rediskey, $count, $value);
                Redis::expire($rediskey, $this->key_timeout);
            }
            else {
                $value = $user['id'] . '|' . $user['name'] . '|' . $user['avatar'];
                //如果已存在的key 增加计量数,如果不存在则插入新的记录
                if (Redis::zrank($rediskey, $value) >= 0)
                {
                    Redis::zincrby($rediskey,$count,$value);
                }
                else {
                    Redis::zadd($rediskey, $count, $value);
                }
            }
            return 0;
        }
        catch(Exception $e)
        {
            return $e;
        }
    }
image.png

2 获取日榜 周榜 月榜
这里日榜是时时数据,周榜和月榜是根据日榜合并一个周或者一个月,过期时间1一个小时,如果存在周榜或者月榜这个key直接查询,如果过期时间到了 则重新合并一个周榜或者月榜。

   /**
     * 获取排行榜单(日|周|月)
     * @param $key 活跃榜|问答榜
     * @param $type 日|月|周
     * @param $user request->user()
     * @return \Exception
     */

    public function getRank($key,$type,$user)
    {
        try {
            //日榜
            if ($type == self::DAY) {
                $rediskey = $key . date('Ymd');
               if(Redis::exists($rediskey)) {//如果当天没人操作
                    $dayRank = Redis::zrevrange($rediskey, 0, $this->ranksize - 1);
                    return $dayRank;
                }
                else
                {
                    return array();
                }
            }
            else
            {
               $rediskeyarray = $this->getKeyArray($key,$type);
               $rediskey = $key . date('Ymd') . $type;
               if(Redis::exists($rediskey))//如果存在这个周榜或月榜Key
               {
                   return Redis::zrevrange($rediskey,0,$this->ranksize-1);
               }
               else
               {
                   Redis::zunionstore($rediskey,$rediskeyarray);
                   Redis::expire($rediskey, 60*60);//设置一小时过期时间
                   return Redis::zrevrange($rediskey,0,$this->ranksize-1);
               }
            }
        } catch (\Exception $e)
        {
            return $e;
        }

    }

    /**
     * 获取月榜 周榜的rediskey array
     * @param $key (用户榜or问答榜)
     * @param $type week or month
     * @return array
     */
    public function getKeyArray($key,$type)
    {
        if($type == self::WEEK)
        {
            $keyarray = array();
            for($x = 0;$x < 7;$x++)
            {
                if($x == 0)
                {
                    $rediskey = $key . date('Ymd');
                }
                else {
                    $rediskey = $key . date('Ymd', strtotime("'-{$x} day'"));
                }
               // var_dump($rediskey);die;
                if(Redis::exists($rediskey))//如果存在这个key 就加入array
                {
                    array_push($keyarray,$rediskey);
                }
            }
            return $keyarray;
        }
        else if($type == self::MONTH)
        {
            $keyarray = array();
            for($x = 0;$x < 30;$x++)
            {
                if($x == 0)
                {
                    $rediskey = $key . date('Ymd');
                }
                else {
                    $rediskey = $key . date('Ymd', strtotime("'-{$x} day'"));
                }
                // var_dump($rediskey);die;
                if(Redis::exists($rediskey))//如果存在这个key 就加入array
                {
                    array_push($keyarray,$rediskey);
                }
            }
            return $keyarray;
        }
    }

如果对您有帮助的 麻烦给个喜欢吧 谢谢

相关文章

  • 使用redis实现排行榜

    写在前面 排行榜在很多地方都能使用到,redis的zset可以很方便地用来实现排行榜功能。本文是一个示例。 聊聊 ...

  • 使用Redis实现一个排行榜功能

    该功能主要使用到Redis的有序集合(SortedSet)来实现的,主要参考的https://blog.csdn....

  • Redis学习笔记

    一、Redis事务 Redis实现了基本的事务功能,但是不具有回滚功能。Redis通过使用 MULTI和EXEC两...

  • Springboot + Mybatis + Redis 实现二

    1.使用redis 实现mybaits 的二级缓存功能:使用Redis实现二级缓存,将运行结果存放在redis当中...

  • redis3.0.4编译安装

    Redis的应用场景:缓存系统、计数器、排行榜、消息队列、实时系统,基本上社交媒体的功能都可以通过Redis实现。...

  • 使用redis的有序集合实现排行榜功能

    游戏中存在各种各样的排行榜,比如玩家的等级排名、分数排名等。玩家在排行榜中的名次是其实力的象征,位于榜单前列的玩家...

  • 使用redis的有序集合实现排行榜功能

    排行榜是业务开发中常见的一个场景,如何设计一个好的数据结构能够满足高效实时的查询,下面我们结合一个实际例子来讨论一...

  • redis设计与实现-复制

    复制 redis主从集群使用复制功能实现,复制有如下特性 redis 2.8以前的复制功能不能高效地处理断线后重复...

  • 分布式爬虫总结和使用

    使用scrapy-redis:Scrapy_redis在scrapy的基础上实现了更多,更强大的功能,具体体现在:...

  • [design draft] Introduction for

    基于Linux的redis C++库的设计与实现 背景现在没有好用的 redis C++ 库(功能缺陷、使用困难、...

网友评论

      本文标题:使用Redis实现一个排行榜功能

      本文链接:https://www.haomeiwen.com/subject/oezrrctx.html