使用Redis實(shí)現(xiàn)一個(gè)排行榜功能

該功能主要使用到Redis的有序集合(SortedSet)來實(shí)現(xiàn)的,主要參考的https://blog.csdn.net/pbymw8iwm/article/details/81130639
來實(shí)現(xiàn)這樣一個(gè)功能,由于最近寫的是PHP項(xiàng)目,所以使用PHP+predis的代碼實(shí)現(xiàn)。

Predis 操作手冊(cè)https://www.cnblogs.com/houdj/p/6859719.html

1、首先實(shí)現(xiàn)對(duì)每個(gè)用戶增加集分的操作:
遇到問題:由于Zset提供了豐富的功能,但是不存在一個(gè)提供判斷ZSet中某個(gè)鍵是否存在指定成員的函數(shù),
新增一個(gè)Set中的Key方法是Zadd,增加Score的方法是Zincrby,無法給一個(gè)不存在的成員增加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 {
            //如果當(dāng)天排行不存在則創(chuàng)建Key并設(shè)置過期時(shí)間
            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 增加計(jì)量數(shù),如果不存在則插入新的記錄
                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 獲取日榜 周榜 月榜
這里日榜是時(shí)時(shí)數(shù)據(jù),周榜和月榜是根據(jù)日榜合并一個(gè)周或者一個(gè)月,過期時(shí)間1一個(gè)小時(shí),如果存在周榜或者月榜這個(gè)key直接查詢,如果過期時(shí)間到了 則重新合并一個(gè)周榜或者月榜。

   /**
     * 獲取排行榜單(日|周|月)
     * @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)) {//如果當(dāng)天沒人操作
                    $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))//如果存在這個(gè)周榜或月榜Key
               {
                   return Redis::zrevrange($rediskey,0,$this->ranksize-1);
               }
               else
               {
                   Redis::zunionstore($rediskey,$rediskeyarray);
                   Redis::expire($rediskey, 60*60);//設(shè)置一小時(shí)過期時(shí)間
                   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))//如果存在這個(gè)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))//如果存在這個(gè)key 就加入array
                {
                    array_push($keyarray,$rediskey);
                }
            }
            return $keyarray;
        }
    }

如果對(duì)您有幫助的 麻煩給個(gè)喜歡吧 謝謝

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容