PHP 怎么更换缓存

wen PHP项目 2

本文目录导读:

PHP 怎么更换缓存

  1. 更换缓存驱动/后端
  2. 清理/刷新缓存
  3. 缓存失效策略
  4. 实际应用场景示例
  5. 最佳实践建议

在 PHP 中更换缓存通常涉及以下几种情况,我来分别说明:

更换缓存驱动/后端

使用缓存抽象层(推荐)

// 以 Laravel 为例,通过配置文件切换
// config/cache.php
'default' => env('CACHE_DRIVER', 'redis'),
// 在 .env 文件中切换
CACHE_DRIVER=redis  // 或 file, database, memcached 等

手动实现缓存类切换

interface CacheInterface {
    public function get($key);
    public function set($key, $value, $ttl = null);
    public function delete($key);
}
// Redis 实现
class RedisCache implements CacheInterface {
    private $redis;
    public function __construct() {
        $this->redis = new Redis();
        $this->redis->connect('127.0.0.1', 6379);
    }
    public function get($key) {
        return $this->redis->get($key);
    }
    public function set($key, $value, $ttl = null) {
        return $this->redis->set($key, $value, $ttl);
    }
    public function delete($key) {
        return $this->redis->del($key);
    }
}
// 文件缓存实现
class FileCache implements CacheInterface {
    private $cacheDir;
    public function __construct($dir) {
        $this->cacheDir = $dir;
        if (!is_dir($dir)) {
            mkdir($dir, 0755, true);
        }
    }
    public function get($key) {
        $file = $this->cacheDir . '/' . md5($key) . '.cache';
        if (file_exists($file)) {
            $data = unserialize(file_get_contents($file));
            if ($data['expire'] > time()) {
                return $data['value'];
            }
            unlink($file);
        }
        return null;
    }
    public function set($key, $value, $ttl = null) {
        $file = $this->cacheDir . '/' . md5($key) . '.cache';
        $data = [
            'value' => $value,
            'expire' => time() + ($ttl ?: 3600)
        ];
        return file_put_contents($file, serialize($data));
    }
    public function delete($key) {
        $file = $this->cacheDir . '/' . md5($key) . '.cache';
        return file_exists($file) ? unlink($file) : true;
    }
}
// 使用工厂模式切换
class CacheFactory {
    public static function create($type) {
        switch ($type) {
            case 'redis':
                return new RedisCache();
            case 'file':
                return new FileCache('/tmp/cache');
            default:
                throw new Exception("不支持的缓存类型");
        }
    }
}
// 使用
$cache = CacheFactory::create('redis'); // 或 'file'
$cache->set('user:1', ['name' => 'John'], 3600);
$user = $cache->get('user:1');

清理/刷新缓存

// 清理特定缓存
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->del('user:1');
// 清理所有缓存(Redis)
$redis->flushAll();
// 清理过期缓存(文件缓存)
function cleanExpiredCache($dir) {
    $files = glob($dir . '/*.cache');
    foreach ($files as $file) {
        $data = unserialize(file_get_contents($file));
        if ($data['expire'] < time()) {
            unlink($file);
        }
    }
}

缓存失效策略

class CacheManager {
    // 版本化缓存键
    public static function versionedKey($key) {
        $version = self::getCacheVersion();
        return "v{$version}:{$key}";
    }
    // 当需要强制刷新时,更新版本号
    public static function invalidateAll() {
        $version = time();
        file_put_contents('/tmp/cache_version', $version);
        return $version;
    }
    private static function getCacheVersion() {
        if (file_exists('/tmp/cache_version')) {
            return file_get_contents('/tmp/cache_version');
        }
        return '1';
    }
}
// 使用版本化缓存
$key = CacheManager::versionedKey('users:list');
$users = $cache->get($key);
if ($users === null) {
    $users = Database::query('SELECT * FROM users');
    $cache->set($key, $users, 3600);
}

实际应用场景示例

// 示例:根据环境切换缓存
class AppCache {
    private static $instance = null;
    private $driver;
    private function __construct() {
        $environment = getenv('APP_ENV') ?: 'production';
        if ($environment === 'production') {
            // 生产环境用 Redis
            $this->driver = CacheFactory::create('redis');
        } else {
            // 开发环境用文件缓存
            $this->driver = CacheFactory::create('file');
        }
    }
    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    public function get($key) {
        return $this->driver->get($key);
    }
    public function set($key, $value, $ttl = 3600) {
        return $this->driver->set($key, $value, $ttl);
    }
}
// 使用
$cache = AppCache::getInstance();
$cache->set('user:profile:1', $profileData, 1800);

最佳实践建议

class CacheHeader {
    // 主动设置缓存过期时间
    header('Cache-Control: max-age=3600');
    header('ETag: "' . md5($content) . '"');
    // 检查 ETag (304 Not Modified)
    if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && 
        $_SERVER['HTTP_IF_NONE_MATCH'] === '"' . $etag . '"') {
        http_response_code(304);
        exit;
    }
}

更换缓存时最重要的几点:

  • 统一接口:使用接口或抽象类避免代码大改
  • 配置分离:将缓存类型配置放在配置文件或 .env 中
  • 版本控制:实现缓存版本控制以便快速失效全部缓存
  • 监控告警:添加缓存命中率监控和失败处理

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