本文目录导读:

在PHP项目中实现文件缓存过期自动清理,常见有以下几种方案:
惰性检查法(推荐)
每次读取缓存时检查过期时间,过期则删除。
class FileCache
{
private $cacheDir;
public function __construct($cacheDir = '/tmp/cache')
{
$this->cacheDir = $cacheDir;
}
public function get($key)
{
$file = $this->getFilePath($key);
if (!file_exists($file)) {
return null;
}
// 读取缓存数据和过期时间
$data = file_get_contents($file);
$cache = unserialize($data);
// 检查是否过期
if (time() > $cache['expire_time']) {
unlink($file); // 删除过期缓存
return null;
}
return $cache['data'];
}
public function set($key, $data, $ttl = 3600)
{
$file = $this->getFilePath($key);
$cache = [
'expire_time' => time() + $ttl,
'data' => $data
];
file_put_contents($file, serialize($cache));
}
private function getFilePath($key)
{
$hash = md5($key);
return $this->cacheDir . '/' . $hash . '.cache';
}
}
定时清理脚本(Cron Job)
创建专门的清理脚本,定期清理过期缓存。
清理脚本 cleanup_cache.php:
<?php
// 缓存目录
$cacheDir = '/tmp/cache';
// 递归清理过期文件
function cleanExpiredCache($dir, $maxLifetime = 3600) {
$files = scandir($dir);
foreach ($files as $file) {
if ($file === '.' || $file === '..') {
continue;
}
$fullPath = $dir . '/' . $file;
if (is_dir($fullPath)) {
cleanExpiredCache($fullPath, $maxLifetime);
} elseif (is_file($fullPath)) {
$fileModTime = filemtime($fullPath);
if (time() - $fileModTime > $maxLifetime) {
unlink($fullPath);
echo "Deleted: $fullPath\n";
}
}
}
}
// 执行清理
cleanExpiredCache($cacheDir);
?>
添加Cron任务:
# 每1小时清理一次过期文件 0 * * * * /usr/bin/php /path/to/cleanup_cache.php # 或者每天凌晨2点清理 0 2 * * * /usr/bin/php /path/to/cleanup_cache.php
懒清理 + 概率清理
请求到达时随机检查清理部分缓存文件。
class ProbabilisticCache
{
private $cacheDir;
private $probability = 0.01; // 1% 概率
public function get($key)
{
// 随机触发清理
if (mt_rand(1, 100) / 100 <= $this->probability) {
$this->partialClean();
}
// 正常获取缓存逻辑...
}
private function partialClean()
{
$files = glob($this->cacheDir . '/*.cache');
$count = min(10, count($files)); // 每次最多清理10个
if ($count === 0) return;
$keys = array_rand($files, $count);
if (!is_array($keys)) {
$keys = [$keys];
}
foreach ($keys as $index) {
$file = $files[$index];
$data = unserialize(file_get_contents($file));
if (time() > $data['expire_time']) {
unlink($file);
}
}
}
}
基于文件系统的优雅方案
class SmartCache
{
private $cacheDir;
public function get($key, $ttl = 3600)
{
$file = $this->getFilePath($key);
if (!file_exists($file)) {
return null;
}
// 使用文件mtime判断过期
if (time() - filemtime($file) > $ttl) {
unlink($file);
return null;
}
return unserialize(file_get_contents($file));
}
public function set($key, $data)
{
$file = $this->getFilePath($key);
file_put_contents($file, serialize($data));
// touch 设置文件修改时间
touch($file);
}
public function cleanAll()
{
$files = glob($this->cacheDir . '/*');
foreach ($files as $file) {
if (is_file($file)) {
unlink($file);
}
}
}
}
使用类似PHPAPC的解决方案
// 如果安装了APCu扩展
class ApcuCache
{
public function get($key)
{
return apcu_fetch($key);
}
public function set($key, $data, $ttl = 3600)
{
apcu_store($key, $data, $ttl);
}
// APCu自动处理过期清理,无需手动操作
}
最佳实践建议
-
生产环境推荐使用方案1(惰性检查),简单高效。
-
结合使用Cron任务,定期清理完全过期的文件。
-
合理设置缓存TTL,避免过多的碎片文件。
-
使用目录分层,避免单个目录文件过多:
// 对缓存key进行目录分层
private function getFilePath($key)
{
$hash = md5($key);
$dir1 = substr($hash, 0, 2);
$dir2 = substr($hash, 2, 2);
$cacheDir = $this->cacheDir . '/' . $dir1 . '/' . $dir2;
if (!is_dir($cacheDir)) {
mkdir($cacheDir, 0777, true);
}
return $cacheDir . '/' . $hash . '.cache';
}
方案可以根据项目规模和需求选择使用,对于小型项目,惰性检查法就足够了;大型项目可以结合Cron任务和惰性检查。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播