PHP 怎么PHP NGINX 缓存

wen PHP项目 2

本文目录导读:

PHP 怎么PHP NGINX 缓存

  1. Nginx 直接缓存(FastCGI Cache)
  2. 按需缓存(跳过指定页面)
  3. PHP 代码级缓存
  4. Redis 缓存
  5. 配合使用的完整示例
  6. Nginx 配置优化
  7. 完整的生产配置示例
  8. 最佳实践建议

我来详细介绍 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,
    ],
];

最佳实践建议

  1. 区分请求类型:GET 请求使用缓存,POST/PUT/DELETE 不缓存
  2. 缓存粒度控制:页面级、片段级、查询级缓存分开管理
  3. 缓存失效策略:主动清理(用户更新)和被动清理(过期)结合
  4. 监控缓存命中率:添加响应头显示缓存状态
  5. 测试环境关闭缓存:避免开发时调试困难

这些方法可以单独或组合使用,根据实际需求选择合适的缓存策略。

抱歉,评论功能暂时关闭!