You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

PHP应用版本动态更新时,如何清理APCu缓存?

解决方案:APCu缓存与应用版本同步清理

针对你在Apache2上运行的Composer构建PHP应用,需要在版本动态变更时清理对应APCu缓存的需求,这里有几个实用的方案,从低侵入的预防式到主动触发式都有,你可以根据自己的场景选择:

1. 版本前缀策略(推荐,低侵入性)

核心思路是给每个模块/包的APCu缓存键加上版本标识前缀,这样版本更新后,旧版本的缓存键会自动被弃用,无需主动删除,同时也能精准控制缓存范围。

实现步骤:

  • 从Composer获取当前应用/模块版本(或者维护一个自定义的版本文件,比如version.php):
    // 获取根包版本
    $composerData = json_decode(file_get_contents(__DIR__ . '/composer.json'), true);
    $appVersion = $composerData['version'];
    
    // 或者获取特定模块版本(比如vendor下的包)
    $packageVersion = json_decode(file_get_contents(__DIR__ . '/vendor/your-vendor/your-package/composer.json'), true)['version'];
    
  • 在设置/读取APCu缓存时,拼接版本前缀:
    // 以模块名为前缀+版本号+具体缓存键
    $cacheKey = sprintf('module_%s:v%s:user_list', 'user', $appVersion);
    
    // 设置缓存
    apcu_store($cacheKey, $userData, 3600);
    
    // 读取缓存
    $cachedData = apcu_fetch($cacheKey);
    
  • 版本更新后,新的缓存会使用新的版本前缀,旧版本的缓存可以通过定期清理任务(比如CRON)删除,或者等待其自然过期。如果需要立即清理旧键,可以用apcu_cache_info遍历并删除匹配旧版本前缀的键:
    function clearOldVersionCache(string $oldVersion) {
        $cacheInfo = apcu_cache_info();
        foreach ($cacheInfo['cache_list'] as $item) {
            if (str_contains($item['info'], ":v{$oldVersion}:")) {
                apcu_delete($item['info']);
            }
        }
    }
    

2. 版本变更触发主动清理

如果需要在版本更新(比如composer update执行完成)后立即清理对应缓存,可以通过Composer的脚本钩子或者手动执行清理脚本实现。

方法A:Composer脚本钩子

composer.json中添加post-update-cmd脚本,版本更新后自动运行清理逻辑:

{
  "scripts": {
    "post-update-cmd": [
      "php ./scripts/clear-apcu-cache.php"
    ]
  }
}

然后编写clear-apcu-cache.php脚本:

<?php
// 注意:如果APCu在CLI下默认未启用,需要在php.ini中开启apcu.enable_cli=1
// 清理所有模块的缓存(或指定版本的缓存)
$cacheInfo = apcu_cache_info();
foreach ($cacheInfo['cache_list'] as $item) {
    // 可以根据模块前缀过滤,比如只清理user模块的缓存
    if (str_starts_with($item['info'], 'module_user:')) {
        apcu_delete($item['info']);
    }
}

echo "APCu cache for updated modules cleared successfully.\n";
?>

方法B:运行时版本检测清理

在应用的入口文件(比如index.php)中,添加版本检测逻辑,当发现版本变更时自动清理对应缓存:

<?php
// 从composer.lock获取当前版本(比composer.json更准确,因为lock文件记录实际安装版本)
$lockData = json_decode(file_get_contents(__DIR__ . '/composer.lock'), true);
$currentVersion = $lockData['packages'][0]['version'];

// 读取上次缓存的版本
$lastVersion = apcu_fetch('app_last_version');

if ($currentVersion !== $lastVersion) {
    // 版本变更,清理所有模块缓存或指定模块
    clearOldVersionCache($lastVersion);
    // 更新缓存的版本记录
    apcu_store('app_last_version', $currentVersion);
}
?>

3. 注意事项

  • APCu CLI启用:如果需要在CLI下运行清理脚本,确保php.iniapcu.enable_cli = On,否则CLI环境无法访问APCu缓存。
  • 权限问题:Apache运行的PHP进程和CLI进程的APCu缓存是独立的(如果用的是APCu的共享内存模式),如果清理脚本在CLI运行,可能无法清理Apache进程的缓存。这种情况下,建议通过Web请求触发清理(比如一个带权限验证的清理接口),或者确保共享内存配置一致。
  • 缓存键规范:提前统一模块/包的缓存键命名规则(比如module_<name>:v<version>:<key>),这样后续清理时更容易匹配过滤。

内容的提问来源于stack exchange,提问作者Mostafa Barmshory

火山引擎 最新活动