一、为什么我们需要缓存?

在软件开发中,"缓存"就像给程序装了个记忆存储器。假设每次用户访问网站都要重新计算数据,就像要求厨师每接待一个客人就重新种一遍蔬菜——效率实在太低!ThinkPHP6为我们提供了多种缓存方案,今天我们就来重点探讨Redis缓存、页面缓存和查询缓存这三种实用方案。

二、Redis缓存配置与实战

1. 环境准备与技术栈说明

技术栈:PHP 8.1 + ThinkPHP6.1 + Redis 6.2.6

确保已安装Redis扩展:

pecl install redis

2. 基础配置示例

修改config/cache.php配置文件:

'redis' => [
    'type'       => 'redis',
    'host'       => '127.0.0.1',
    'port'       => 6379,
    'password'   => '',
    'select'     => 0, // 默认库
    'timeout'    => 0,
    'expire'     => 0, // 永不过期
    'persistent' => false,
    'prefix'     => 'tp6_cache:', // 键前缀
],

3. 基础操作示例

// 写入缓存(带60秒过期)
Cache::store('redis')->set('user_123', ['name' => '张三'], 60);

// 批量操作(原子性操作保证)
Cache::store('redis')->setMultiple([
    'article_1' => '内容1',
    'article_2' => '内容2'
], 3600);

// 模糊删除示例
$keys = Cache::store('redis')->getCache()->keys('user_*');
Cache::store('redis')->deleteMultiple($keys);

三、页面缓存全攻略

1. 中间件配置

创建app/middleware/PageCache.php:

<?php
declare (strict_types=1);

namespace app\middleware;

use think\cache\driver\Redis;
use think\Response;

class PageCache
{
    public function handle($request, \Closure $next)
    {
        $cacheKey = 'page_'.md5($request->url());
        
        if ($content = app('cache')->get($cacheKey)) {
            return response($content);
        }

        $response = $next($request);
        app('cache')->set($cacheKey, $response->getContent(), 300);
        return $response;
    }
}

2. 路由配置示例

// 应用页面缓存中间件
Route::group(function(){
    Route::get('article/:id', 'Article/detail');
})->middleware(PageCache::class);

四、查询缓存的高阶玩法

1. 数据库操作缓存

// 带缓存的查询(缓存3600秒)
Db::name('user')
  ->cache('all_users', 3600)
  ->select();

// 更新时清除缓存
Db::name('user')
  ->where('id', 1)
  ->update(['name'=>'李四']);
Cache::delete('all_users');

2. 模型缓存实践

class User extends Model
{
    // 启用自动缓存
    protected $cacheTime = 7200; 

    public function profile()
    {
        return $this->hasOne(Profile::class)->cache(true);
    }
}

// 使用示例
$user = User::where('id', 1)
          ->cache('user_full_info', 600)
          ->with('profile')
          ->find();

五、关联技术详解

1. 缓存标签管理

// 使用标签批量管理
Cache::tag('user_data')
     ->set('user_1', $data1)
     ->set('user_2', $data2);

// 清除整个标签的缓存
Cache::clear('tag', 'user_data');

2. 多级缓存策略

// 组合文件缓存和Redis缓存
$data = Cache::remember('complex_data', function(){
    // 查询数据库的逻辑
    return Db::name('data')->select();
}, 600, 'file'); // 文件缓存过期后使用Redis

六、应用场景深度解析

1. Redis最佳实践场景

  • 秒杀系统库存缓存
  • 实时排行榜数据
  • 分布式会话存储
  • 热点数据缓存

2. 页面缓存适用情况

  • 企业官网等静态内容
  • CMS系统文章详情页
  • 不常变动的帮助文档
  • 高并发入口页面

七、技术选型优缺点对比

1. Redis缓存优势

  • 支持多种数据结构
  • 读写性能高达10万QPS
  • 内置持久化机制
  • 支持分布式集群

2. 潜在风险点

  • 单线程模型可能阻塞
  • 内存成本较高
  • 数据丢失风险(RDB模式)
  • 冷启动时可能缓存击穿

八、避坑指南与注意事项

  1. 缓存穿透防护
// 空值缓存示例
public function getUser($id)
{
    $key = "user_{$id}";
    if (!$data = Cache::get($key)) {
        $data = User::find($id);
        Cache::set($key, $data ?: 'NULL', 300);
    }
    return $data === 'NULL' ? null : $data;
}
  1. 雪崩预防策略
// 随机过期时间设置
$expire = 3600 + mt_rand(0, 600);
Cache::set('hot_data', $value, $expire);
  1. 使用规范建议
  • 缓存键命名统一规范
  • 单个缓存数据不超过1MB
  • 监控Redis内存使用率
  • 避免长查询阻塞服务

九、技术方案总结

当我们合理使用ThinkPHP6的缓存体系时,就像给系统装上了涡轮增压器。Redis作为高速缓存层承担热点数据存储,页面缓存拦截重复计算压力,查询缓存则精准优化复杂查询。记住:没有完美的技术方案,只有最适合场景的选择。