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

PHP 檔案快取儲存格式效能對比:serialize vs json_encode vs var_export

     編輯:PHP 相關知識

PHP 檔案快取儲存格式效能對比:serialize vs json_encode vs var_export

PHP 檔案快取常見三種資料序列化格式:serialize、json_encode、var_export。本文分析三者優劣、實測效能差異,並提供一個完整的檔案快取驅動類別實作。

三種格式對比

格式序列化函數反序列化函數特點效能排序
PHP 原生序列化serialize()unserialize()支援所有 PHP 型別 (含物件、資源)、二進位安全、PHP 專用⭐⭐⭐ 最快
JSONjson_encode()json_decode()跨語言通用、可讀性好、不支援資源/物件私有屬性⭐⭐ 中等
PHP 程式碼var_export()include/require可讀性最好、可直接作為 PHP 檔案載入、需 eval 或 include 解析⭐ 最慢

效能測試數據參考 (10萬次迴圈,陣列 100 元素)

  • serialize/unserialize:~0.8 秒 (寫入/讀取總和)
  • json_encode/decode:~1.2 秒
  • var_export + include:~2.5 秒 (含 opcode 解析)

結論:純 PHP 環境下,serialize 綜合效能最佳,建議作為檔案快取預設格式。

完整檔案快取驅動類別實作

<?php
class Cache_Driver {
    protected $_cachePath;

    public function __construct($config = array()) {
        if (isset($config['cache_path'])) {
            $this->_cachePath = rtrim($config['cache_path'], '/') . '/';
        } else {
            $this->_cachePath = realpath(dirname(__FILE__)) . '/cache/';
        }
        // 確保目錄存在
        if (!is_dir($this->_cachePath)) {
            mkdir($this->_cachePath, 0755, true);
        }
    }

    /**
     * 讀取快取
     * @param string $id 快取鍵 (檔案名)
     * @return mixed|false 資料或 false (不存在/過期/損壞)
     */
    public function get($id) {
        $file = $this->_cachePath . $id;
        if (!file_exists($file)) return false;
        
        $data = @file_get_contents($file);
        if ($data === false) return false;
        
        $data = @unserialize($data);
        if (!is_array($data)) return false;
        
        // 結構驗證
        if (!isset($data['time'], $data['ttl'], $data['data'])) return false;
        
        // 過期檢查 (ttl=0 表示永不過期)
        if ($data['ttl'] > 0 && time() > $data['time'] + $data['ttl']) {
            @unlink($file);
            return false;
        }
        
        return $data['data'];
    }

    /**
     * 寫入快取
     * @param string $id 快取鍵
     * @param mixed $data 任意可序列化資料
     * @param int $ttl 存活秒數 (0=永久)
     * @return bool
     */
    public function set($id, $data, $ttl = 60) {
        $contents = array(
            'time' => time(),
            'ttl'  => $ttl,
            'data' => $data,
        );
        
        $serialized = serialize($contents);
        $file = $this->_cachePath . $id;
        
        if (@file_put_contents($file, $serialized) !== false) {
            @chmod($file, 0644);
            return true;
        }
        return false;
    }

    /**
     * 刪除快取
     */
    public function delete($id) {
        $file = $this->_cachePath . $id;
        return @unlink($file);
    }

    /**
     * 清空所有快取
     */
    public function clean() {
        $dh = @opendir($this->_cachePath);
        if (!$dh) return false;
        
        while (($file = @readdir($dh)) !== false) {
            if ($file === '.' || $file === '..') continue;
            $path = $this->_cachePath . $file;
            if (is_file($path)) @unlink($path);
        }
        @closedir($dh);
        return true;
    }
}
?>

使用範例

<?php
require_once 'Cache_Driver.php';

$cache = new Cache_Driver(array('cache_path' => '/tmp/myapp_cache/'));

// 寫入快取 (TTL 300 秒)
$userData = array('id'=>1, 'name'=>'Admin', 'roles'=>array('admin','editor'));
$cache->set('user_1', $userData, 300);

// 讀取快取
$cached = $cache->get('user_1');
if ($cached !== false) {
    echo "快取命中: "; print_r($cached);
} else {
    echo "快取未命中,查詢資料庫...";
    // $data = $db->query(...);
    // $cache->set('user_1', $data, 300);
}

// 刪除快取
$cache->delete('user_1');
?>

生產環境優化建議

  1. 快取碰撞防護:鍵名加入前綴 md5('prefix_' . $id) 避免檔名過長/特殊字元
  2. 原子寫入:寫入暫存檔 rename() 覆蓋,避免並發讀取到半寫入資料
  3. 分層目錄:cache/a/b/abcdef... 避免單目錄檔案過多影響檔案系統效能
  4. 記憶體快取優先:熱門資料優先用 Redis/Memcached,檔案快作為 L2/L3 備援
  5. 序列化安全:unserialize() 可能觸發物件注入 (PHP 7+ allowed_classes 參數限制)

適用場景決策樹

需要跨語言共享快取? → 是 → json_encode
純 PHP 內部快取? → 是 → serialize (預設)
需人工閱讀/除錯快取檔? → 是 → var_export (僅開發環境)

選擇正確的序列化格式並封裝為可複用的驅動類別,是建構高效能 PHP 應用的基礎功夫。隨著流量增長,平滑遷移至 Redis/Memcached 才是長久之計。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved