本文目录导读:

我为您设计一个完整的PHP多级缓存架构方案,从外层到内层逐步解析。
整体架构示意
┌─────────────────────────────────────────────────────────┐
│ 客户端请求 │
└────────────────────┬────────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────┐
│ L1: CDN缓存层 (静态资源) │
│ - 图片、CSS、JS、视频等 │
└────────────────────┬────────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────┐
│ L2: 页面缓存层 (HTML输出) │
│ - Redis/Nginx FastCGI Cache │
└────────────────────┬────────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────┐
│ L3: 应用数据缓存层 (业务数据) │
│ - Redis主要缓存 + 本地进程缓存(APCu) │
└────────────────────┬────────────────────────────────────┘
▼
│ L4: 数据库层 (MySQL/MongoDB) │
└─────────────────────────────────────────────────────────┘
各层缓存实现方案
L1 CDN缓存层
// 配置CDN缓存头
header('Cache-Control: public, max-age=86400, s-maxage=86400');
header('ETag: "' . md5($fileContent) . '"');
// 静态资源缓存策略
class CDNCacheManager {
public function setStaticCacheHeaders($fileType) {
$cacheTimes = [
'image' => 604800, // 7天
'css' => 2592000, // 30天
'js' => 2592000, // 30天
'html' => 3600 // 1小时
];
header('Cache-Control: public, max-age=' . $cacheTimes[$fileType]);
header('Vary: Accept-Encoding');
}
// 版本控制,解决缓存失效问题
public function getVersionedUrl($path, $version) {
return $path . '?v=' . $version;
}
}
L2 页面缓存层
class PageCacheManager {
private $redis;
private $cacheKeyPrefix = 'page:';
private $ttl = 3600;
public function __construct() {
$this->redis = new Redis();
$this->redis->connect('127.0.0.1', 6379);
}
/**
* 获取页面缓存
*/
public function getContent($requestUri) {
// 生成缓存key,包含URL和参数
$cacheKey = $this->cacheKeyPrefix . md5($requestUri);
// 尝试从缓存获取
$cached = $this->redis->get($cacheKey);
if ($cached !== false) {
// 恢复HTML内容
return unserialize($cached);
}
return null;
}
/**
* 存储页面缓存
*/
public function setContent($requestUri, $html) {
$cacheKey = $this->cacheKeyPrefix . md5($requestUri);
// 序列化存储
$this->redis->setex(
$cacheKey,
$this->ttl,
serialize([
'content' => $html,
'timestamp' => time()
])
);
}
/**
* 页面缓存失效策略
*/
public function invalidatePages($patterns) {
foreach ($patterns as $pattern) {
$keys = $this->redis->keys($this->cacheKeyPrefix . $pattern);
foreach ($keys as $key) {
$this->redis->del($key);
}
}
}
}
L3 应用数据缓存层
class AppCacheManager {
private $redis;
private $localCache = [];
private $apcuEnabled;
private $ttlMap = [
'user_profile' => 3600,
'product_list' => 300,
'hot_search' => 600,
'initial_data' => 1800
];
public function __construct() {
$this->redis = new Redis();
$this->redis->connect('127.0.0.1', 6379);
$this->redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP);
$this->apcuEnabled = function_exists('apcu_add');
}
/**
* 分层获取缓存数据:APCu -> Redis -> DB
*/
public function get($key, $callback, $ttl = null) {
// L3.1: 检查本地进程缓存(APCu)
if ($this->apcuEnabled) {
$data = apcu_fetch($key);
if ($data !== false) {
return $data;
}
}
// L3.2: 检查Redis缓存
$data = $this->redis->get($key);
if ($data !== false) {
// 写入本地缓存
if ($this->apcuEnabled) {
apcu_store($key, $data, 60); // 本地缓存只有60秒
}
return $data;
}
// L3.3: 缓存未命中,从数据库获取
$data = $callback();
// 写入各级缓存
$effectiveTtl = $ttl ?? $this->ttlMap[$key] ?? 3600;
$this->redis->setex($key, $effectiveTtl, $data);
if ($this->apcuEnabled) {
apcu_store($key, $data, 60);
}
return $data;
}
/**
* 批量获取缓存,避免击穿
*/
public function getMulti(array $keys) {
// 首先从APCu获取
$localData = [];
if ($this->apcuEnabled) {
$localData = apcu_fetch($keys);
$missingKeys = array_diff($keys, array_keys($localData));
} else {
$missingKeys = $keys;
}
// 从Redis获取缺失的
$redisData = [];
if (!empty($missingKeys)) {
$redisData = $this->redis->mget($missingKeys);
$redisData = array_combine($missingKeys, $redisData);
// 处理Redis缓存未命中的情况
$stillMissing = [];
foreach ($redisData as $k => $v) {
if ($v === false) {
$stillMissing[] = $k;
}
}
// 从数据库获取(略)
}
return $localData + $redisData;
}
/**
* 缓存防击穿策略
*/
public function getWithMutex($key, $callback, $ttl = null) {
// 使用Redis的SETNX实现互斥锁
$lockKey = $key . ':lock';
// 尝试获取缓存
$data = $this->redis->get($key);
if ($data !== false) {
return $data;
}
// 尝试获取锁
$locked = $this->redis->set($lockKey, 1, ['NX', 'EX' => 10]);
if ($locked) {
// 获取到锁,从数据库获取数据
$data = $callback();
$effectiveTtl = $ttl ?? $this->ttlMap[$key] ?? 3600;
$this->redis->setex($key, $effectiveTtl, $data);
// 释放锁
$this->redis->del($lockKey);
// 写入本地缓存
if ($this->apcuEnabled) {
apcu_store($key, $data, 60);
}
return $data;
} else {
// 未获取到锁,等待然后重试
usleep(50000); // 50ms
return $this->redis->get($key);
}
}
}
多级缓存协调层
class MultiLevelCache {
private $pageCache;
private $appCache;
private $config;
public function __construct() {
$this->config = [
'page_cache_enabled' => true,
'app_cache_enabled' => true,
'cache_prefix' => 'app:',
'default_ttl' => 3600
];
$this->pageCache = new PageCacheManager();
$this->appCache = new AppCacheManager();
}
/**
* 统一缓存入口
*/
public function handleRequest($request) {
// 1. 页面级缓存检查
if ($this->config['page_cache_enabled']) {
$pageContent = $this->pageCache->getContent($request->getUri());
if ($pageContent) {
return $this->response($pageContent['content']);
}
}
// 2. 执行业务逻辑
$data = $this->processBusinessLogic($request);
// 3. 生成HTML
$html = $this->renderView($data);
// 4. 存储页面缓存
if ($this->config['page_cache_enabled']) {
$this->pageCache->setContent($request->getUri(), $html);
}
return $this->response($html);
}
/**
* 动态数据处理
*/
public function getBusinessData($key, $callback) {
// 应用级缓存
return $this->appCache->getWithMutex(
$this->config['cache_prefix'] . $key,
$callback
);
}
/**
* 局部缓存刷新策略
*/
public function refreshData($keys) {
foreach ($keys as $key) {
// 删除应用缓存
$this->appCache->delete($key);
}
// 删除相关页面缓存
$this->pageCache->invalidatePages($keys);
}
/**
* 缓存命中率监控
*/
public function getCacheStats() {
// 使用内存存储获取缓存统计
$stats = [
'redis_hits' => apcu_fetch('cache_redis_hits'),
'redis_misses' => apcu_fetch('cache_redis_misses'),
'apcu_hits' => apcu_fetch('cache_apcu_hits'),
'apcu_misses' => apcu_fetch('cache_apcu_misses'),
'page_caches' => apcu_fetch('cache_page_count')
];
return $stats;
}
}
缓存优化策略代码
class CacheOptimization {
// 缓存预热
public function preWarmCache() {
$hotData = [
'hot_search' => '热点搜索',
'navigation' => '导航数据',
'recommendation' => '推荐内容'
];
foreach ($hotData as $key => $callback) {
// 预先获取数据
$data = $this->loadDataFromDB($callback);
// 写入Redis
$this->redis->setex($key, 3600, $data);
// 写入APCu
apcu_store($key, $data, 60);
}
}
// 缓存穿透处理
public function handleCachePenetration($key, $callback) {
// 使用值-1表示不存在的数据
$data = $this->redis->get($key);
if ($data === -1) {
return null; // 已知不存在的数据
}
if ($data === false) {
// 先从数据库获取
$result = $callback();
if ($result === null) {
// 缓存空结果,防止穿透
$this->redis->setex($key, 300, -1); // 5分钟
} else {
$this->redis->setex($key, 3600, $result);
}
return $result;
}
return $data;
}
// 缓存雪崩预防
public function setWithRandomTTL($key, $data, $baseTTL) {
// 添加随机偏移,避免同一时间失效
$randomOffset = mt_rand(0, 300); // 0-5分钟随机
$effectiveTTL = $baseTTL + $randomOffset;
$this->redis->setex($key, $effectiveTTL, $data);
}
}
监控与性能优化
class CacheMonitor {
public function logCacheEvent($event, $key, $layer) {
$logData = [
'timestamp' => time(),
'event_type' => $event, // hit/miss/expire
'cache_key' => $key,
'cache_layer' => $layer,
'request_time' => microtime(true)
];
// 异步发送到监控系统
$this->asyncLog($logData);
}
public function getCacheHitRate() {
// 计算各级缓存的命中率
return [
'cdn' => $this->calculateHitRate('cdn'),
'page' => $this->calculateHitRate('page'),
'redis' => $this->calculateHitRate('redis'),
'apcu' => $this->calculateHitRate('apcu')
];
}
private function calculateHitRate($layer) {
// 从统计数据计算
$stats = $this->getStatsFromMetrics($layer);
if ($stats['total'] == 0) {
return 0;
}
return $stats['hits'] / $stats['total'] * 100;
}
}
核心要点:
- 分层缓存:CDN -> 页面缓存 -> 应用缓存 -> 数据库
- 分布式与本地结合:Redis(分布式)+ APCu(本地进程)
- 防击穿:使用互斥锁
- 防穿透:缓存空值
- 防雪崩:随机过期时间
- 监控统计:命中率、延迟监控
建议:
- 根据业务特点调整各层TTL
- 实时数据不缓存,热点数据优先缓存
- 使用缓存版本控制方便失效
- 确保缓存与数据源的一致性
这种架构能显著提升PHP应用性能,适用于高并发场景。