本文目录导读:

在 PHP 中实现 FastCGI 缓存,主要有以下几种常见方案,让我详细说明:
Nginx FastCGI Cache(最常用)
基本配置
# 在 http 块中定义缓存路径
http {
fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=mycache:100m
inactive=60m max_size=500m;
# 缓存配置
server {
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 mycache;
fastcgi_cache_valid 200 60m;
fastcgi_cache_valid 404 1m;
# 跳过带 cookie 的请求
fastcgi_cache_bypass $cookie_session;
fastcgi_no_cache $cookie_session;
# 设置缓存标识
fastcgi_cache_key "$request_method|$request_uri";
}
}
}
高级配置
# 缓存变量定义
map $request_uri $cache_bypass {
default 0;
~*admin 1; # admin 路径不缓存
~*login 1;
}
server {
location ~ \.php$ {
# ... 基础配置 ...
# 动态跳过缓存
fastcgi_cache_bypass $cache_bypass;
fastcgi_no_cache $cache_bypass;
# 带客户端标识
fastcgi_cache_key "$request_method|$http_host|$request_uri|$http_x_request_id";
# 缓存 POST 请求
fastcgi_cache_methods GET HEAD;
# 自定义缓存过期头
add_header X-Cache $upstream_cache_status;
}
}
PHP 代码层缓存
使用 APCu 缓存
<?php
class PageCache {
private static $prefix = 'page_cache:';
public static function get($key, $ttl = 60) {
$full_key = self::$prefix . $key;
$data = apcu_fetch($full_key, $success);
if ($success) {
return $data;
}
// 获取页面内容
$content = self::renderPage();
// 存入缓存
apcu_store($full_key, $content, $ttl);
return $content;
}
public static function clear($key = null) {
if ($key) {
apcu_delete(self::$prefix . $key);
} else {
apcu_clear_cache();
}
}
}
// 使用示例
$cache_key = md5($_SERVER['REQUEST_URI']);
$page = PageCache::get($cache_key);
echo $page;
?>
文件缓存
<?php
class FileCache {
private $cacheDir;
public function __construct($cacheDir = '/tmp/cache') {
$this->cacheDir = $cacheDir;
if (!is_dir($cacheDir)) {
mkdir($cacheDir, 0755, true);
}
}
public function get($key, $ttl = 3600) {
$filePath = $this->cacheDir . '/' . md5($key) . '.cache';
if (file_exists($filePath) && (time() - filemtime($filePath) < $ttl)) {
return file_get_contents($filePath);
}
return null;
}
public function set($key, $data, $ttl = 3600) {
$filePath = $this->cacheDir . '/' . md5($key) . '.cache';
file_put_contents($filePath, $data);
}
public function clear() {
array_map('unlink', glob($this->cacheDir . '/*.cache'));
}
}
?>
PHP + Redis/Memcached 缓存
Redis 缓存
<?php
class RedisPageCache {
private $redis;
private $ttl;
public function __construct($ttl = 60) {
$this->redis = new Redis();
$this->redis->connect('127.0.0.1', 6379);
$this->ttl = $ttl;
}
public function start($key = null) {
if (!$key) {
$key = $_SERVER['REQUEST_URI'];
}
$key = 'cache:' . md5($key);
$cached = $this->redis->get($key);
if ($cached) {
echo $cached;
return true;
}
// 开始输出缓冲
ob_start();
$this->currentKey = $key;
return false;
}
public function end() {
$content = ob_get_clean();
if ($this->currentKey) {
$this->redis->setex($this->currentKey, $this->ttl, $content);
}
echo $content;
}
public function clear($key = null) {
if ($key) {
$this->redis->del('cache:' . md5($key));
} else {
// 清除所有缓存
$keys = $this->redis->keys('cache:*');
if (!empty($keys)) {
$this->redis->del($keys);
}
}
}
}
// 使用示例
$cache = new RedisPageCache(300); // 缓存5分钟
if (!$cache->start()) { // 缓存未命中时执行
// 页面内容生成
echo "页面重要内容";
$cache->end(); // 保存缓存
}
?>
综合最佳实践配置
# Nginx 配置
http {
# 缓存配置
fastcgi_cache_path /var/cache/nginx levels=1:2
keys_zone=FASTCGI_CACHE:100m
inactive=60m max_size=500m
use_temp_path=off;
# 缓存级别配置
fastcgi_cache_key "$scheme$request_method$host$request_uri";
# 缓存控制变量
map $http_cookie $cookie_key {
default "nocache";
~*session "withsession";
}
server {
listen 80;
location ~ \.php$ {
# PHP-FPM 配置
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
# 缓存设置
fastcgi_cache FASTCGI_CACHE;
fastcgi_cache_valid 200 301 302 60m;
fastcgi_cache_valid 404 403 1m;
# 跳过需要动态处理的内容
fastcgi_cache_bypass $cookie_key;
fastcgi_no_cache $cookie_key;
# 添加缓存标识
add_header X-Cache-Status $upstream_cache_status;
add_header Cache-Control "public, max-age=60";
# 更多高级配置
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
# 压缩缓存
gzip_vary on;
}
}
}
PHP 侧缓存控制
<?php
// 设置缓存相关头
header('Cache-Control: public, max-age=60');
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 60) . ' GMT');
// 支持条件请求
if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
$etag = $_SERVER['HTTP_IF_NONE_MATCH'];
if ($etag == $current_etag) {
header('HTTP/1.1 304 Not Modified');
exit;
}
}
header('ETag: ' . $current_etag);
// 输出缓冲区
ob_start();
echo "动态内容";
// 最后输出
ob_end_flush();
?>
性能调优建议
Nginx 缓存配置优化
# 高级缓存策略 fastcgi_cache_key "$scheme$request_method$host$request_uri"; fastcgi_cache_use_stale error timeout invalid_header http_500 http_502; fastcgi_cache_lock on; fastcgi_cache_lock_timeout 5s; fastcgi_cache_revalidate on; fastcgi_cache_background_update on;
PHP 缓存注意事项
<?php缓存策略
class CacheManager {
public static function shouldCache() {
// 检查是否是 GET 请求
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
return false;
}
// 检查是否有登录状态
if (isset($_SESSION['user_id'])) {
return false;
}
// 检查是否为动态页面
$uri = $_SERVER['REQUEST_URI'];
if (preg_match('/\/(admin|login|logout|cart)\b/', $uri)) {
return false;
}
return true;
}
}
?>
选择哪种方案取决于你的具体需求:
- Nginx FastCGI Cache:性能最好,适合大多数场景
- Redis/Memcached:适合分布式、需要动态管理的场景
- APCu/文件缓存:适合简单、单机部署
- 组合使用:通常在 CDN + Nginx 缓存 + Redis 多层组合效果最佳