Redis实现排行榜思路
想必看到这篇文章的uu们,应该都是刚学redis过来的,本篇文章是博主在学习redis后实现的排行榜功能,使用的是tp6框架,其他Web框架自行配置即可!
Redis实现排行榜思路
一、tp6配置redis缓存config\cache.php
<?php
// +----------------------------------------------------------------------
// | 缓存设置
// | redis服务器要确保开启,建议在有redis基础下再学习本博
// +----------------------------------------------------------------------
return [
// 默认缓存驱动
'default' => env('cache.driver', 'redis'),
// 缓存连接方式配置
'stores' => [
'redis' => [
// 驱动方式
'type' => 'redis',
'host' => '127.0.0.1',
'port' => 6379,
],
// 更多的缓存连接
],
];
这个redis的配置文件可以参考thinkphp的源码,有相关的配置选项文件,选择redis的即可
vendor\topthink\framework\src\think\cache\driver\Redis.php
二、使用zset有序集合收集热度信息
zadd 添加有序集合
zcard 统计有序集合个数
zrem 移除有序集合的元素
/**
* 添加帖子名称和热度
*/
public function add()
{
//使用接口测试工具添加表单信息
$data['title'] = request()->post('title');
$data['hot'] = (int)request()->post('hot', 0);
//添加redis
cache()->zadd('topic', $data['hot'], $data['title']);
//redis只保存前5条数据
if (cache()->zcard('topic') > 5) {
//移除排名最后的数据
cache()->zrem('topic', cache()->zrange('topic', '0', '-1')[0]);
}
return json_encode(['code'=>200,'msg'=>'insert success']);
}
使用apipost添加数据,使用reids命令行查看缓存数据
redis命令:zrevrange topic 0 -1 withscores
参考:https://www.redis.net.cn/tutorial/3512.html
三、突破:在controller实现热度与时间绑定
在实现基础的排行榜后,剩余的就是业务逻辑的事,比如以时间节点作为分类,或者是热点信息由点赞+转发+评论等一系列算法构成,接下来介绍单纯使用redis实现时间上的分类!
源码路径:https://github.com/xiaopacairq/tpAdmin
- 热度缓存到reids时,将当前的时间戳拼接到热度后面
/**
* 添加帖子名称和热度
*/
public function add()
{
$data['title'] = request()->post('title');
$data['hot'] = (int)request()->post('hot', 0);
//添加redis
cache()->zadd('topic_v4', $data['hot'] . time(), $data['title']);
return json_encode(['code'=>200,'msg'=>'insert success']);
}
- 以时间为条件做一些判断逻辑
这里的逻辑可自定义,主要是知道实现的思路,核心点是1,第2和第3点只是作为参考
public function index()
{
//获取get作为条件判断
$type = request()->get('type');
if (empty($type) || $type == 'all') {
$where = null;
}
if ($type == 'day') {
$where = $this->actionDay();
}
if ($type == 'week') {
$where = $this->actionWeek();
}
if ($type == 'month') {
$where = $this->actionMonth();
}
if ($type == 'year') {
$where = $this->actionYear();
}
//取出redis数据,拼接数组
$data['res'] = [];
$title_list = cache()->zrevrange('topic_v4', '0', '-1');
if (!empty($title_list)) {
for ($i = 0; $i < count($title_list); $i++) {
$score = (int)cache()->zscore('topic_v4', $title_list[$i]);
$add_time = strtotime(date("Y-m-d H:i:s", substr($score, -10)));
if ($where == null) {
$data['res'][] = [
'title' => $title_list[$i],
'hot' => str_replace($add_time, "", $score),
'add_time' => $add_time
];
} else if ($add_time >= $where[0] && $add_time <= $where[1]) {
$data['res'][] = [
'title' => $title_list[$i],
'hot' => str_replace($add_time, "", $score),
'add_time' => $add_time
];
}
}
}
halt($data);
}
拼接出一个二维数组后,客户端调用即可获取相应排名即可!
时间区间函数
// 获取当天的开始结束时间
public function actionDay()
{
$time = time();
$start = strtotime(date("Y-m-d H:i:s", mktime(0, 0, 0, date("m", $time), date("d", $time), date("Y", $time))));
$end = strtotime(date("Y-m-d H:i:s", mktime(23, 59, 59, date("m", $time), date("d", $time), date("Y", $time))));
return [$start, $end];
}
// 获取当前周的开始结束时间
public function actionWeek()
{
$time = time();
$start = strtotime(date("Y-m-d H:i:s", mktime(0, 0, 0, date("m", $time), date("d", $time) - date("w", $time) + 1, date("Y", $time))));
$end = strtotime(date("Y-m-d H:i:s", mktime(23, 59, 59, date("m", $time), date("d", $time) - date("w", $time) + 7, date("Y", $time))));
return [$start, $end];
}
// 获取月的开始结束时间
public function actionMonth()
{
$start = mktime(0, 0, 0, date('m'), 1, date('y'));
$end = mktime(23, 59, 59, date('m'), date('t'), date('y'));
return [$start, $end];
}
// 获取年的开始结束时间
public function actionYear()
{
$date = date('Y-m-d H:i:s');
$start = strtotime(date(date("Y-01-01 00:00:00", strtotime("$date"))));
$end = strtotime(date('Y-12-31 23:59:59', strtotime("$date")));
return [$start, $end];
}
本博到此结束,thinkphp,以及勤劳的自己!