本文目录导读:

- 第一类:PHP 代码层面(字节码缓存)
- 第二类:应用数据缓存(业务逻辑层)
- 第三类:HTTP 客户端缓存(浏览器层)
- 第四类:页面级缓存(全页/片段缓存)
- 第五类:数据库级缓存(底层优化)
- 实际项目中的综合策略(最佳实践)
- 核心代码示例(Redis + 防击穿)
- 总结与建议
PHP 缓存策略是一个非常广泛的话题,涵盖了从代码层面到应用层面,再到服务器/数据库层面的多个维度。
根据缓存的数据位置和作用域,我将其分为五大类,并附上具体的实现建议:
第一类:PHP 代码层面(字节码缓存)
这是最基础、见效最快的缓存,主要用于解决 PHP 脚本每次请求都需要重新编译的问题。
- OPcache(推荐):
- 原理:PHP 是解释型语言,每次请求都需要将
.php文件编译成字节码再执行,OPcache 将编译后的字节码存储在共享内存中,下次请求直接读取,省去编译时间。 - 配置建议:
opcache.enable=1,opcache.memory_consumption=128,opcache.max_accelerated_files=10000。 - 说明:这是 PHP 7+ 后的标配,必须开启。
- 原理:PHP 是解释型语言,每次请求都需要将
第二类:应用数据缓存(业务逻辑层)
这是开发中最常接触的,用于缓存数据库查询结果、API 调用结果或复杂计算的结果。
文件缓存(File Cache)
- 实现:将数据序列化后写入
.php或.txt文件,读取时通过file_get_contents和unserialize获取。 - 优点:无需安装额外扩展,部署简单。
- 缺点:I/O 开销大,不适合高并发分布式环境。
- 适用:单机小项目,或存储配置信息(如 Laravel 的配置缓存
config:cache)。
内存缓存(Memcached / Redis)
这是当前主流的高性能方案。
- Memcached:
- 特点:纯内存、简单、速度快(但数据类型单一,仅支持字符串)。
- 适用:用于 Session 共享、简单的数据对象缓存。
- Redis(推荐):
- 特点:支持丰富的数据结构(String、Hash、List、Set、Sorted Set),支持数据持久化(RDB/AOF),支持分布式锁和发布订阅。
- 适用:复杂业务缓存、排行榜、计数器、队列。
- 框架集成:Laravel、Symfony 等框架都内置了 Cache 门面,可以快速切换驱动。
第三类:HTTP 客户端缓存(浏览器层)
这是为了减少服务器压力,加快用户端加载速度。
- HTTP 头信息控制:
- 通过
Cache-Control和Expires设置浏览器缓存静态资源(图片、CSS、JS)。 - ETag / Last-Modified:用于条件请求(
If-None-Match),如果资源未修改,服务器返回304 Not Modified,不传输响应体。
- 通过
- CDN 缓存:将静态资源分发到边缘节点,用户就近获取。
- PHP 中的应用:
- 对于动态生成的页面,如果数据变化不频繁,可以设置
Cache-Control: max-age=3600,让浏览器或 CDN 缓存页面。
- 对于动态生成的页面,如果数据变化不频繁,可以设置
第四类:页面级缓存(全页/片段缓存)
如果页面不是实时交互的,可以考虑整体缓存输出。
- 全页静态化(输出缓冲):
- 使用 PHP 的
ob_start()将页面内容缓冲,然后写入.html文件,下次请求直接读取 HTML 文件,跳过 PHP 执行。 - 示例:
if (file_exists($cache_file) && (time() - filemtime($cache_file) < 3600)) { include $cache_file; // 直接输出静态文件 exit; } ob_start(); // ... PHP 业务逻辑 ... $html = ob_get_contents(); file_put_contents($cache_file, $html); ob_end_flush();
- 使用 PHP 的
- Edge Side Includes(ESI)或片段缓存:
- 如 Laravel 的
Blade模板引擎支持@cache指令,将模板中的部分区块(如侧边栏)缓存,而核心内容动态更新。
- 如 Laravel 的
第五类:数据库级缓存(底层优化)
虽然不属于 PHP 直接操作,但对 PHP 性能影响巨大。
- MySQL 查询缓存:
注意:MySQL 8.0 已移除该功能,不推荐依赖。
- SQL 语句预处理与索引:
这是最根本的缓存逻辑,减少昂贵的 Join 查询。
- 慢查询日志与缓存联动:
- 将复杂查询的结果存入 Redis,
$hot_data = Redis::get('complex_query_key') ?: DB::select(...)。
- 将复杂查询的结果存入 Redis,
实际项目中的综合策略(最佳实践)
以一个高并发 API 项目为例,推荐的“缓存金字塔”策略是:
- 第一层(最快):OPcache —— 确保 PHP 代码本身执行快。
- 第二层(业务):Redis —— 针对热点数据,设置
TTL(过期时间)防止缓存雪崩。- 缓存穿透:查询空值也缓存,或使用布隆过滤器。
- 缓存击穿:使用互斥锁(
SETNX)重构缓存。 - 缓存雪崩:给 TTL 加随机值,防止同一时段大面积失效。
- 第三层(网络):CDN —— 对于静态资源,直接由 CDN 拦截,根本不算 PHP 进程。
- 第四层(协议):HTTP 缓存 —— 强制浏览器复用缓存,减少请求数。
核心代码示例(Redis + 防击穿)
function getProductInfo($id) {
$cacheKey = "product:{$id}";
// 1. 尝试从 Redis 获取
$data = Redis::get($cacheKey);
if ($data !== false) {
return unserialize($data);
}
// 2. 缓存不存在,尝试获取锁(防止缓存击穿)
$lockKey = "lock:" . $cacheKey;
if (Redis::set($lockKey, 1, ['nx', 'ex' => 10])) {
try {
// 3. 查数据库
$product = DB::table('products')->where('id', $id)->first();
if ($product) {
// 4. 写缓存,设置过期时间
Redis::setex($cacheKey, 3600, serialize($product));
} else {
// 5. 空值缓存,防止穿透(设置较短过期时间)
Redis::setex($cacheKey, 60, serialize(null));
}
return $product;
} finally {
// 6. 释放锁
Redis::del($lockKey);
}
} else {
// 其他请求等待或递归重试
usleep(50000); // 等待 50ms
return getProductInfo($id); // 递归重试
}
}
总结与建议
| 策略类型 | 技术方案 | 效率 | 复杂度 | 适用场景 |
|---|---|---|---|---|
| 代码缓存 | OPcache | ⭐⭐⭐⭐⭐ | 低(配置即可) | 所有生产环境必开 |
| 数据缓存 | Redis / Memcached | ⭐⭐⭐⭐ | 中 | 热点数据、Session、接口加速 |
| 页面缓存 | ob_start / 静态化 | ⭐⭐⭐⭐⭐ | 低 | 首页、活动页、不常变化的页面 |
| HTTP缓存 | Cache-Control / CDN | ⭐⭐⭐⭐⭐ | 低 | 静态资源(CSS/JS/图片) |
| 数据库缓存 | MySQL Query Cache(旧) | 一般 | 高 | 已过时,推荐交给中间件处理 |
最核心的三大原则:
- 能开OPcache就开(基本零成本)。
- 优先用Redis做业务层缓存(灵活可控)。
- 不要存“永久”,一定要设 TTL(长期运行时不至于内存爆炸)。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播