該功能主要使用到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è)喜歡吧 謝謝