本文目录导读:

我来详细介绍 PHP 与 Nginx 缓存的几种方式和实现方法:
Nginx 直接缓存(FastCGI Cache)
基础配置
# 在 nginx.conf 或虚拟主机配置中
fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=php_cache:10m max_size=1g inactive=60m;
server {
listen 80;
server_name example.com;
# PHP 处理
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# 启用缓存
fastcgi_cache php_cache;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_valid 200 60m;
fastcgi_cache_use_stale error timeout invalid_header http_500;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
}
# 静态文件直接缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
}
按需缓存(跳过指定页面)
server {
# 缓存规则
set $skip_cache 0;
# 登录页缓存 1 分钟
if ($request_uri = /login) { set $skip_cache 1; }
# POST 请求不缓存
if ($request_method = POST) { set $skip_cache 1; }
location ~ \.php$ {
fastcgi_cache_key "$scheme$request_method$host$request_uri";
# 跳过缓存
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
fastcgi_cache_valid 200 60m;
}
}
PHP 代码级缓存
页面缓存
<?php
class PageCache {
private $cacheDir = '/tmp/page_cache/';
private $cacheTime = 3600; // 1小时
public function start() {
$key = md5($_SERVER['REQUEST_URI']);
$cacheFile = $this->cacheDir . $key . '.html';
if (file_exists($cacheFile) && (time() - filemtime($cacheFile)) < $this->cacheTime) {
echo file_get_contents($cacheFile);
exit;
}
ob_start([$this, 'saveCache']);
}
public function saveCache($content) {
$key = md5($_SERVER['REQUEST_URI']);
file_put_contents($this->cacheDir . $key . '.html', $content);
return $content;
}
public function clearCache() {
$files = glob($this->cacheDir . '*.html');
foreach ($files as $file) {
unlink($file);
}
}
}
// 使用
$cache = new PageCache();
$cache->start();..
?>
Redis 缓存
PHP 使用 Redis
<?php
class RedisCache {
private $redis;
private $prefix = 'page:';
public function __construct() {
$this->redis = new Redis();
$this->redis->connect('127.0.0.1', 6379);
}
public function get($key) {
$key = $this->prefix . md5($key);
return $this->redis->get($key);
}
public function set($key, $data, $ttl = 3600) {
$key = $this->prefix . md5($key);
return $this->redis->setex($key, $ttl, $data);
}
public function clear($pattern = '*') {
$keys = $this->redis->keys($this->prefix . $pattern);
foreach ($keys as $key) {
$this->redis->del($key);
}
}
}
// 使用
$cache = new RedisCache();
$content = $cache->get($_SERVER['REQUEST_URI']);
if (!$content) {
ob_start();
// 页面内容
$content = ob_get_clean();
$cache->set($_SERVER['REQUEST_URI'], $content);
}
echo $content;
?>
配合使用的完整示例
<?php
// API 缓存管理器
class ApiCache {
private static $instance = null;
private $redis;
private $queryCache = [];
private function __construct() {
$config = require 'config/cache.php';
$this->redis = new Redis();
$this->redis->connect($config['host'], $config['port']);
}
public static function getInstance() {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
// 处理 GET 请求缓存
public function handleGetRequest($uri) {
if ($_SERVER['REQUEST_METHOD'] !== 'GET') return;
$cacheKey = 'api:' . md5($uri . '?' . http_build_query($_GET));
// 尝试获取缓存
$cached = $this->redis->get($cacheKey);
if ($cached) {
header('Content-Type: application/json');
echo $cached;
exit;
}
// 启动缓冲区
ob_start(function($content) use ($cacheKey) {
$ttl = 300; // 5分钟
$this->redis->setex($cacheKey, $ttl, $content);
return $content;
});
}
// 清除特定缓存
public function clearApiCache($pattern = '*') {
$keys = $this->redis->keys('api:' . $pattern);
foreach ($keys as $key) {
$this->redis->del($key);
}
}
// 数据库查询缓存
public function cacheQuery($key, $callback, $ttl = 600) {
$cacheKey = 'query:' . md5($key);
if ($cached = $this->redis->get($cacheKey)) {
return unserialize($cached);
}
$result = $callback();
$this->redis->setex($cacheKey, $ttl, serialize($result));
return $result;
}
// 全站缓存管理
public function clearAllCache() {
$this->redis->flushAll();
}
}
Nginx 配置优化
# http 块中
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off;
server {
# 启用 gzip 压缩
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_min_length 1024;
# 浏览器缓存
location / {
add_header Cache-Control "public, max-age=3600";
}
# API 缓存
location /api/ {
proxy_cache my_cache;
proxy_cache_key "$scheme$request_method$host$request_uri";
proxy_cache_valid 200 60m;
proxy_cache_valid 404 1m;
}
}
完整的生产配置示例
// config/cache.php
return [
'redis' => [
'host' => '127.0.0.1',
'port' => 6379,
'timeout' => 2,
],
'page' => [
'enable' => true,
'ttl' => 3600,
'except' => ['/login', '/cart', '/user'],
],
'api' => [
'enable' => true,
'ttl' => 300,
'rate_limit' => 60,
],
];
最佳实践建议
- 区分请求类型:GET 请求使用缓存,POST/PUT/DELETE 不缓存
- 缓存粒度控制:页面级、片段级、查询级缓存分开管理
- 缓存失效策略:主动清理(用户更新)和被动清理(过期)结合
- 监控缓存命中率:添加响应头显示缓存状态
- 测试环境关闭缓存:避免开发时调试困难
这些方法可以单独或组合使用,根据实际需求选择合适的缓存策略。