手上有个 ThinkPHP 5.1 的企业官网,前台每次打开页面都要查十几次数据库:站点信息、公司信息、导航菜单、产品分类、政策条款……全在 Common 基类的 initialize() 里,每个页面都跑一遍。
装了 Redis 之后,第一次访问缓存起来,后面的请求直接读 Redis,数据库查询降到接近零。
问题分析
前台的 Common.php 是所有控制器的基类,initialize() 里干了这些事:
protected function initialize(){
$this->assign('site_info', $this->getSiteInfo()); // 查1次
$this->assign('recommended_section', ...); // 查1次
$this->assign('company_info', $this->getCompanyInfo()); // 查1次
$this->assign('recommended_category', ...); // 查1次
$this->assign('all_product_category', ...); // 查1次
$this->assign('inquiry_product', ...); // 读配置
$this->assign('all_country', ...); // 读配置
$this->assign('privacy_policy', $this->getPolicy(1)); // 查1次
$this->assign('logistics_policy', $this->getPolicy(2)); // 查1次
$this->assign('top', $this->getTopNav()); // 查1次
}加上 get_system_val() 每次也查数据库,一个页面下来轻松 15+ 次数据库查询。这些数据其实很少变化,完全没必要每次都查。
方案选择
三个选择:文件缓存、Redis、Memcached。
选了 Redis,原因:
- 速度最快,毫秒级响应
- 支持数据结构,方便后续扩展
- 宝塔面板一键安装,零配置
- ThinkPHP 5.1 原生支持
安装步骤
宝塔面板操作:
- 软件商店 → 搜索 Redis → 安装
- 软件商店 → PHP 7.4 → 安装扩展 → redis
- 重启 PHP
验证:
redis-cli ping # 返回 PONG
php -r "echo extension_loaded('redis') ? 'OK' : 'NO';" # 返回 OKThinkPHP 配置
修改 config/cache.php:
return [
'type' => 'redis',
'host' => '127.0.0.1',
'port' => 6379,
'password' => '',
'select' => 0,
'timeout' => 3,
'expire' => 3600,
'prefix' => 'xm_',
'serialize' => true,
];给查询加缓存
改造模式很简单,每个方法开头加缓存读取,结尾加缓存写入:
public function getSiteInfo(){
$cached = cache('site_info');
if ($cached) return $cached;
// 原来的数据库查询...
$site_info = db('site')->where('id', 1)->find();
// 处理数据...
cache('site_info', $site_info, 3600); // 缓存1小时
return $site_info;
}一共改了 6 个方法:getSiteInfo、getCompanyInfo、getRecommendedSection、getProductsCategory、getTopNav、getPolicy。
get_system_val 也加缓存
这个函数被调用得最频繁,每次读一个系统配置值都要查数据库。用 static 变量做请求内缓存:
function get_system_val($code){
static $cache = [];
if (!isset($cache[$code])) {
$cache[$code] = db('system_config')->where('code', $code)->value('val');
}
return $cache[$code];
}后台修改时清缓存
数据被缓存了,后台修改数据后要及时清缓存,不然前台看到的还是旧数据:
// 系统设置保存后
\think\facade\Cache::clear();后台菜单也缓存
后台的 left_nav() 函数每次请求查 3 次数据库生成菜单。菜单在登录后基本不变,缓存到 session 里:
function left_nav(){
$cacheKey = 'left_nav_' . $user_id;
$cached = session($cacheKey);
if ($cached) {
echo $cached;
return;
}
// 生成菜单...
session($cacheKey, $html);
echo $html;
}效果
- 首次访问:查数据库,结果写入 Redis,耗时正常
- 后续访问:直接读 Redis,数据库查询降到接近 0
- 缓存过期:1 小时后自动刷新
- 手动更新:后台修改数据时自动清缓存
对于这种内容不常变化的企业官网,Redis 缓存的性价比非常高。
评论
暂无评论