首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 文件緩存工具類實戰:高併發下的輕量級頁面緩存方案

     編輯:PHP 相關知識

緩存策略對比

文件緩存類 Cache 完整實現

<?php
class Cache {
    private $dir;
    private $lifetime;
    private $cacheId;
    private $ext = '.cache.php';

    public function __construct($dir = '', $lifetime = 1800) {
        $this->dir = $dir ?: sys_get_temp_dir() . '/php_cache/';
        $this->lifetime = $lifetime;
        $this->initDir();
        $this->cacheId = $this->getCacheId();
    }

    private function initDir() {
        if (!is_dir($this->dir)) {
            if (!mkdir($this->dir, 0755, true)) {
                throw new RuntimeException("無法創建緩存目錄: {$this->dir}");
            }
        }
        // 安全防護:禁止直接訪問緩存文件
        $htaccess = $this->dir . '.htaccess';
        if (!file_exists($htaccess)) {
            file_put_contents($htaccess, "Deny from all\n");
        }
    }

    private function getCacheId() {
        $url = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
        return $this->dir . md5($url) . $this->ext;
    }

    // 判斷緩存是否有效
    public function isValid() {
        if (!file_exists($this->cacheId)) return false;
        $mtime = filemtime($this->cacheId);
        return (time() - $mtime) < $this->lifetime;
    }

    // 加載緩存(有效則輸出並終止腳本)
    public function load() {
        if ($this->isValid()) {
            // 發送緩存標識頭(便於調試)
            header('X-Cache: HIT');
            include $this->cacheId;
            exit;
        }
        // 無效則開啟輸出緩衝準備生成新緩存
        header('X-Cache: MISS');
        ob_start();
    }

    // 寫入緩存
    public function write($content = '') {
        $content = $content ?: ob_get_contents();
        ob_end_flush();
        $tmpFile = $this->cacheId . '.tmp';
        if (file_put_contents($tmpFile, $content) === false) {
            throw new RuntimeException("緩存寫入失敗: {$tmpFile}");
        }
        // 原子重命名避免讀到半寫文件
        rename($tmpFile, $this->cacheId);
    }

    // 清除單個緩存
    public function clean() {
        if (file_exists($this->cacheId)) unlink($this->cacheId);
    }

    // 清除所有緩存
    public function cleanAll() {
        $files = glob($this->dir . '*' . $this->ext);
        foreach ($files as $f) unlink($f);
    }

    // 獲取緩存信息
    public function getInfo() {
        return [
            'file' => $this->cacheId,
            'exists' => file_exists($this->cacheId),
            'size' => file_exists($this->cacheId) ? filesize($this->cacheId) : 0,
            'mtime' => file_exists($this->cacheId) ? date('Y-m-d H:i:s', filemtime($this->cacheId)) : null,
            'lifetime' => $this->lifetime,
        ];
    }
}

使用方法:極簡三步

<?php
// 1. 頁面最頂部引入並初始化
require_once 'Cache.php';
$cache = new Cache('./cache/', 300); // 5 分鐘緩存

// 2. 嘗試加載緩存(命中直接輸出並 exit)
$cache->load();

// 3. 你的業務邏輯代碼(查詢數據庫、渲染模板等)
echo "<h1>動態生成的內容</h1>";
echo "當前時間: " . date('H:i:s');
$users = $db->query('SELECT * FROM users LIMIT 10');
foreach ($users as $u) echo $u['name'] . '<br>';

// 4. 頁面底部寫入緩存
$cache->write();

進階用法

手動刷新緩存

// URL 帶參數強制刷新:page.php?cache_act=refresh
if (isset($_GET['cache_act']) && $_GET['cache_act'] === 'refresh') {
    $cache->clean();
    // 可選:重定向去除參數避免循環刷新
    header('Location: ' . strtok($_SERVER['REQUEST_URI'], '?'));
    exit;
}

差異化緩存(按用戶/設備/語言)

// 修改 getCacheId() 包含更多維度
private function getCacheId() {
    $keyParts = [
        $_SERVER['REQUEST_URI'],
        $_SESSION['user_id'] ?? 'guest',
        $_COOKIE['lang'] ?? 'zh',
        isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'Mobile') ? 'mobile' : 'desktop',
    ];
    return $this->dir . md5(implode('|', $keyParts)) . $this->ext;
}

緩存標籤/分組清理(需維護索引文件)

// 寫入時記錄標籤
$tags = ['user_list', 'homepage'];
$indexFile = $this->dir . '_tags.index.php';
$index = file_exists($indexFile) ? include $indexFile : [];
foreach ($tags as $tag) $index[$tag][] = $this->cacheId;
file_put_contents($indexFile, 'dir . '_tags.index.php';
    if (!file_exists($indexFile)) return;
    $index = include $indexFile;
    if (isset($index[$tag])) {
        foreach ($index[$tag] as $file) @unlink($file);
        unset($index[$tag]);
        file_put_contents($indexFile, '

性能優化建議

  • SSD 盤:文件緩存目錄掛載在 SSD/NVMe 上
  • tmpfs 內存盤:mount -t tmpfs -o size=512m tmpfs /var/www/cache 將緩存目錄掛載到內存
  • Nginx fastcgi_cache:在 Nginx 層面直接緩存 FastCGI 響應,繞過 PHP 執行,性能提升 10x+
  • 預熱機制:部署後腳本自動請求熱門頁面生成緩存
  • 監控指標:命中率、平均響應時間、緩存目錄大小、inode 使用率

避坑指南

  • ❌ 緩存用戶敏感信息(賬單、個人中心)
  • ❌ 緩存目錄可通過 Web 直接訪問(必須 .htaccess / Nginx 禁止)
  • ❌ 緩存Key 衝突導致數據錯亂(包含完整 URI + 區分維度)
  • ❌ 無緩存清理策略導致磁盤佔滿(定時任務清理過期/定期全量清理)
  • ✅ 緩存內容包含 CSRF Token 等動態數據時需佔位符替換
  • ✅ 開發環境禁用緩存或極短過期時間

文件緩存是「無 Redis 環境」或「靜態化頁面」場景下的最佳選擇,代碼簡單、零依賴、易維護。高併發核心業務請上 Redis + Nginx 多級緩存架構。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
類型存儲介質讀寫速度適用場景
文件緩存磁盤 (SSD 推薦)中等中小流量、靜態化頁面、配置緩存、無 Redis 環境
內存緩存 (Redis/Memcached)RAM極快高併發、分佈式、會話存儲、熱點數據
Opcode 緩存 (OPcache)共享內存極快PHP 代碼編譯緩存,生產環境必開
HTTP 緩存 (ETag/Last-Modified)客戶端/代理最快(無請求)靜態資源、REST API、CDN 配合