Featured image of post 你应该了解的PHP缓存技术

你应该了解的PHP缓存技术

PHP 缓存技术全面解析:编译缓存、数据缓存、内存缓存、分布式缓存

缓存是现代系统中必不可少的模块,已经成为高并发高性能架构的关键组件。

缓存概念

什么是缓存

缓存是将程序或系统经常要调用的对象存在内存中,以便快速调用,不必重复创建实例。这样可以减少系统开销,提高系统效率。

缓存分类

类型说明示例
文件缓存数据存储在磁盘上XML、JSON、序列化文件
内存缓存存储在静态内存区域Application、静态 Map
分布式缓存跨进程、跨域访问Redis、Memcached

PHP 缓存类型

PHP 编译缓存

PHP 是解释型语言,执行过程包括:

  1. 编译过程:读取文件,编译成中间码
  2. 执行过程:直接执行中间码

问题

  • 即使代码文件未改变,也会被重新编译
  • 引用文件也需要重新编译

解决方案:PHP 编译缓存工具

工具说明
APCAlternative PHP Cache
OPcachePHP 内置(PHP 5.5+)
XCache国产高性能编译器

启用 OPcache

; php.ini
zend_extension=opcache.so

; 基本配置
opcache.enable=1
opcache.memory_consumption=128
opcache.max_accelerated_files=10000
opcache.revalidate_freq=2

PHP 数据缓存

类型缓存内容工具
数据库缓存查询结果Memcached、Redis
模板缓存页面模板Smarty、Twig

缓存优势

1. 提升性能

  • 减少数据库查询
  • 加速远程调用
  • 降低响应时间

2. 缓解数据库压力

┌─────────┐    请求    ┌─────────┐
│   用户   │ ───────▶ │  Nginx  │
└─────────┘          └────┬────┘
                         │
                   ┌─────▼─────┐
                   │   缓存层   │ ◀──────┐ 命中
                   └─────┬─────┘        │
                         │ 未命中      │
                   ┌─────▼─────┐        │
                   │  数据库   │ ──────┘ 写入
                   └───────────┘

常用缓存方案

1. 文件缓存

<?php

/**
 * 简单文件缓存类
 */
class FileCache
{
    private $cacheDir;
    private $expire = 3600;

    public function __construct(string $cacheDir = './cache', int $expire = 3600)
    {
        $this->cacheDir = rtrim($cacheDir, '/');
        $this->expire = $expire;
        
        if (!is_dir($this->cacheDir)) {
            mkdir($this->cacheDir, 0755, true);
        }
    }

    /**
     * 设置缓存
     */
    public function set(string $key, $value, ?int $expire = null): bool
    {
        $file = $this->getFilePath($key);
        $data = [
            'value' => $value,
            'expire' => time() + ($expire ?? $this->expire),
        ];
        
        return file_put_contents(
            $file,
            serialize($data),
            LOCK_EX
        ) !== false;
    }

    /**
     * 获取缓存
     */
    public function get(string $key, $default = null)
    {
        $file = $this->getFilePath($key);
        
        if (!file_exists($file)) {
            return $default;
        }
        
        $content = file_get_contents($file);
        $data = unserialize($content);
        
        if ($data['expire'] < time()) {
            unlink($file);
            return $default;
        }
        
        return $data['value'];
    }

    /**
     * 删除缓存
     */
    public function delete(string $key): bool
    {
        $file = $this->getFilePath($key);
        return file_exists($file) ? unlink($file) : true;
    }

    /**
     * 清除所有缓存
     */
    public function clear(): bool
    {
        $files = glob($this->cacheDir . '/*');
        foreach ($files as $file) {
            if (is_file($file)) {
                unlink($file);
            }
        }
        return true;
    }

    private function getFilePath(string $key): string
    {
        return $this->cacheDir . '/' . md5($key) . '.cache';
    }
}

// 使用示例
$cache = new FileCache('./cache', 3600);

// 设置缓存
$cache->set('user_1', ['name' => 'John', 'email' => 'john@example.com']);

// 获取缓存
$user = $cache->get('user_1');
if ($user) {
    echo "缓存命中: " . json_encode($user);
} else {
    // 从数据库获取
    $user = fetchUserFromDB(1);
    $cache->set('user_1', $user);
}

2. Memcached

<?php

/**
 * Memcached 缓存封装
 */
class MemcachedCache
{
    private $memcached;

    public function __construct(array $servers = [])
    {
        $this->memcached = new Memcached();
        
        if (empty($servers)) {
            $servers = [
                ['127.0.0.1', 11211, 100],
            ];
        }
        
        $this->memcached->addServers($servers);
    }

    /**
     * 设置缓存
     */
    public function set(string $key, $value, int $ttl = 0): bool
    {
        return $this->memcached->set($key, $value, $ttl);
    }

    /**
     * 获取缓存
     */
    public function get(string $key)
    {
        return $this->memcached->get($key);
    }

    /**
     * 删除缓存
     */
    public function delete(string $key): bool
    {
        return $this->memcached->delete($key);
    }

    /**
     * 增加数值
     */
    public function increment(string $key, int $offset = 1)
    {
        return $this->memcached->increment($key, $offset);
    }

    /**
     * 清除所有缓存
     */
    public function flush(): bool
    {
        return $this->memcached->flush();
    }

    /**
     * 获取多条缓存
     */
    public function getMulti(array $keys): array
    {
        return $this->memcached->getMulti($keys);
    }

    /**
     * 批量设置
     */
    public function setMulti(array $items, int $ttl = 0): bool
    {
        return $this->memcached->setMulti($items, $ttl);
    }
}

// 使用示例
$cache = new MemcachedCache([
    ['127.0.0.1', 11211],
]);

// 设置缓存
$cache->set('user_1', ['name' => 'John'], 3600);

// 获取缓存
$user = $cache->get('user_1');

// 计数器
$cache->set('page_views', 0);
$cache->increment('page_views');

3. Redis

<?php

/**
 * Redis 缓存封装
 */
class RedisCache
{
    private $redis;

    public function __construct(string $host = '127.0.0.1', int $port = 6379)
    {
        $this->redis = new Redis();
        $this->redis->connect($host, $port);
    }

    /**
     * 设置缓存
     */
    public function set(string $key, $value, ?int $ttl = null): bool
    {
        $value = is_array($value) ? json_encode($value) : $value;
        
        if ($ttl === null) {
            return $this->redis->set($key, $value);
        }
        
        return $this->redis->setex($key, $ttl, $value);
    }

    /**
     * 获取缓存
     */
    public function get(string $key)
    {
        $value = $this->redis->get($key);
        
        if ($value === null) {
            return null;
        }
        
        // 尝试 JSON 解码
        $decoded = json_decode($value, true);
        return json_last_error() === JSON_ERROR_NONE ? $decoded : $value;
    }

    /**
     * 删除缓存
     */
    public function delete(string $key): int
    {
        return (int) $this->redis->del($key);
    }

    /**
     * 判断键是否存在
     */
    public function exists(string $key): bool
    {
        return $this->redis->exists($key) > 0;
    }

    /**
     * 设置过期时间(秒)
     */
    public function expire(string $key, int $seconds): bool
    {
        return $this->redis->expire($key, $seconds);
    }
}

// 使用示例
$redis = new RedisCache();
$redis->set('foo', 'bar', 60);
var_dump($redis->get('foo'));
$redis->delete('foo');

提示:生产环境建议加连接池、统一 Key 前缀、超时与熔断,并结合业务决定哪些数据适合落在 Redis。

选型小结

场景建议
单机小规模、持久化不重要文件缓存 / APCu
多节点共享会话、计数Memcached
丰富数据结构 + 持久化Redis

结合 OPcache 减少 PHP 脚本重复编译,再配合数据缓存,通常能在成本可控的前提下显著提升站点响应速度。

© 2016-2026 Yison. All rights reserved.
使用 Hugo 构建
主题 StackJimmy 设计