该功能主要使用到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;
}
}

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;
}
}
如果对您有帮助的 麻烦给个喜欢吧 谢谢
网友评论