由于是个人的服务器,配置方面还是很低的,因此,我决定优化一下自己的博客网站的文章查看功能。
优化之前,系统的逻辑是“用户每查看一次文章详情,就会将累计点击次数保存到数据库中”,这种频繁更新数据库的方式在高并发的情况下,显然是不合理的。
为此,我决定利用redis缓存来优化网站,操作步骤如下:
1、点击率的计数值保存在redis缓存中(该方法在文章详情展示时候调用)
/** * 累计文章点击率 * @param $article */ public function incrementHits($article) { $key = $this->getHitsKey(); $redis = RedisService::getInstance(); $hits = $redis->zscore($key, $article['id']); if (!$hits) { $redis->zadd($key, [ $article['id'] => $article['hits'] ]); } $redis->zincrby($key, 1, $article['id']); }
2、直接从缓存中查询点击率
/** * 获取文章点击率 * @param $article * @return int */ public function getHits($article): int { $hits = RedisService::getInstance()->zscore($this->getHitsKey(), $article['id']); return $hits ?: $article['hits']; }
3、创建点击率刷新任务:HitsRefresh
php artisan make:command HitsRefresh
4、编写HitsRefresh命令,核心代码如下
/** * 刷新数据表中的点击率 */ public function storeHits() { $members = RedisService::getInstance()->zscan($this->getHitsKey(), 0); foreach ($members[1] as $id => $hits) { ArticleModel::query()->where('id', '=', $id)->update([ 'hits' => $hits ]); } }
5、将执行命令添加到定时任务中(每分钟执行一次)
# larastu crontab * * * * * www-data cd /data/www/larastu && php artisan schedule:run 2>&1
6、任务执行频率设置为每天执行一次
/** * Define the application's command schedule. * * @param Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { // 每天凌晨刷新一次点击率 $schedule->command('hits:refresh') ->daily() ->runInBackground() ->sendOutputTo(storage_path('logs/schedule.log'), true); }