用装饰器模式实现多层缓存:让PHP应用更快更稳

为什么要做多层缓存?

想象这样一个场景:你的PHP应用每次访问数据库都要花1秒钟,用户抱怨页面加载太慢。这时候你会想到加缓存------但只用一层缓存够吗?

比如:

  • 内存缓存虽然快,但重启服务数据就没了
  • Redis缓存能持久化,但网络请求也有开销
  • 文件缓存最可靠,但磁盘读写速度有限

多层缓存的思路很简单

把最快的缓存放在最前面,就像快递柜一样------

  1. 优先从内存取(速度最快)
  2. 内存没有再查Redis(速度中等)
  3. Redis没有最后查文件或数据库(速度最慢但最可靠)

这样既能减少对慢速存储的访问 ,又能保证数据最终可用性


为什么选择装饰器模式?

假设我们要实现这样的调用链:

内存缓存 → Redis缓存 → 文件缓存 → 数据库

如果用传统继承方式:

php 复制代码
// 伪代码:噩梦般的多层继承
class MemoryThenRedisThenFileCache extends FileCache {
    // 要重写所有方法...
}

装饰器模式就像俄罗斯套娃:

php 复制代码
// 真实使用示例:自由组合
$cache = new MemoryCache(
    new RedisCache(
        new FileCache(
            new DatabaseSource()
        ),
        [
			'host' => '127.0.0.1'
            'port' => 6379,
            'password' => null,
            'ttl' => 3600
		]
    ),
	300
	1024
);

三大优势

  1. 灵活组合:随时换缓存顺序,比如把Redis放最外层
  2. 代码干净:每个类只关注自己的缓存逻辑
  3. 易于扩展:新增缓存类型只需写一个新类

怎么用?三行代码搞定

该模块已经在我PHP的常用工具库中实现,可以通过composer集成到项目 点击查看GitHub与文档

可以通过该命令安装: composer require hejunjie/tools

假设已经安装了这个composer包:

php 复制代码
use Hejunjie\Tools\Cache\Decorators;
// 1. 创建基础数据源(比如数据库查询类)
$dbSource = new DatabaseSource();

// 2. 像套娃一样包裹缓存层
$cache = new Decorators\MemoryCache(           // 第一层:内存
    new Decorators\RedisCache(                 // 第二层:Redis - 未安装 redis 则去掉该层
        new Decorators\FileCache(              // 第三层:文件
            $dbSource, 						   // 第四层:数据库(用户自定义)
            '[文件]缓存文件夹路径',
            '[文件]缓存时长(秒)'
        ),
        '[redis]配置'
        '[redis]前缀'
        '[redis]是否持久化链接'
    ),
    '[内存]缓存时长(秒)',
    '[内存]缓存数量(防止内存溢出)'
);

// 3. 无感知使用(自动走缓存链)
$data = $cache->get('user_123');    // 自动按 内存 → Redis → 文件 → 数据库 顺序查找,找到后立即返回不继续向后调用;返回时根据查找顺序倒序返回并自动存储

$cache->set('user_123', '张三');    // 同时更新所有缓存层

实际效果对比

场景 无缓存 单层缓存 三层缓存
读取速度 1.2s 0.3s 0.05ms
数据库压力 100% 30% <5%
服务重启后 正常 缓存失效 仍有文件缓存兜底

为什么推荐这个设计?

  1. 像搭积木一样简单

    随时增删缓存层,比如临时去掉Redis:

    php 复制代码
    $cache = new Decorators\MemoryCache(           // 第一层:内存
        new Decorators\FileCache(                  // 第二层:文件
            $dbSource, 							   // 第三层:数据库(用户自定义)
            '[文件]缓存文件夹路径',
            '[文件]缓存时长(秒)'
        ),
        '[内存]缓存时长(秒)',
        '[内存]缓存数量(防止内存溢出)'
    );
  2. 安全有保障

    • 文件缓存自动加锁防止冲突
    • Redis自动重连机制
    • 内存缓存限制最大条目数
  3. 看得见的效果

    内存缓存自带统计面板:

    php 复制代码
    print_r($cache->getStats());
    /* 输出:
    [
        'hits' => 2953,      // 命中次数
        'misses' => 47,      // 未命中次数
        'hit_rate' => 0.984, // 命中率98.4%
        'items' => 1024      // 当前缓存条目
    ]
    */

适合什么场景?

  • 高频读取的数据(如商品信息)
  • 需要快速响应的API接口
  • 数据库压力大的系统
  • 希望服务重启后快速恢复

总结

通过装饰器模式实现多层缓存,就像给应用穿上了多层保暖衣:

  • 内层(内存) :最贴身,响应最快
  • 中层(Redis) :保持温度,持久化
  • 外层(文件) :防风防雪,绝对可靠

这种设计用简单的代码实现了灵活高效的缓存策略,下次当你遇到性能瓶颈时,不妨试试这种"套娃式"的解决方案吧!

相关推荐
BingoGo1 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack1 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端
BingoGo2 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php
JaguarJack2 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php·服务端
JaguarJack3 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
后端·php·服务端
BingoGo3 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
php
JaguarJack4 天前
告别 Laravel 缓慢的 Blade!Livewire Blaze 来了,为你的 Laravel 性能提速
后端·php·laravel
郑州光合科技余经理5 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
QQ5110082855 天前
python+springboot+django/flask的校园资料分享系统
spring boot·python·django·flask·node.js·php
WeiXin_DZbishe5 天前
基于django在线音乐数据采集的设计与实现-计算机毕设 附源码 22647
javascript·spring boot·mysql·django·node.js·php·html5