本文目录导读:

为PHP项目的第三方接口数据实现本地缓存,常见方案及最佳实践如下:
文件缓存(简单场景)
基础实现
<?php
class FileCache {
private $cacheDir;
public function __construct($cacheDir = '/tmp/api_cache/') {
$this->cacheDir = $cacheDir;
if (!is_dir($this->cacheDir)) {
mkdir($this->cacheDir, 0755, true);
}
}
public function get($key) {
$file = $this->cacheDir . md5($key) . '.cache';
if (!file_exists($file)) {
return false;
}
$data = unserialize(file_get_contents($file));
if ($data['expire'] < time()) {
unlink($file);
return false;
}
return $data['value'];
}
public function set($key, $value, $ttl = 3600) {
$data = [
'expire' => time() + $ttl,
'value' => $value
];
file_put_contents(
$this->cacheDir . md5($key) . '.cache',
serialize($data)
);
}
}
使用示例
$cache = new FileCache('/var/www/cache/');
$apiKey = 'weather_data';
if (!$data = $cache->get($apiKey)) {
// 请求第三方接口
$data = file_get_contents('https://api.weather.com/v1/...');
$data = json_decode($data, true);
// 缓存10分钟
$cache->set($apiKey, $data, 600);
}
return $data;
Redis缓存(高性能推荐)
安装与配置
# 安装Redis扩展 pecl install redis # 或使用composer composer require predis/predis
封装缓存类
<?php
class RedisCache {
private $redis;
private $prefix = 'api_cache:';
public function __construct($config = []) {
$this->redis = new Redis();
$this->redis->connect(
$config['host'] ?? '127.0.0.1',
$config['port'] ?? 6379
);
// 设置密码
if (!empty($config['password'])) {
$this->redis->auth($config['password']);
}
}
public function get($key) {
$data = $this->redis->get($this->prefix . $key);
return $data ? unserialize($data) : false;
}
public function set($key, $value, $ttl = 3600) {
$cacheKey = $this->prefix . $key;
$this->redis->setex($cacheKey, $ttl, serialize($value));
}
public function delete($key) {
$this->redis->del($this->prefix . $key);
}
public function exists($key) {
return $this->redis->exists($this->prefix . $key);
}
}
缓存策略封装
<?php
class ApiCacheManager {
private $cache;
private $defaultTTL = 300; // 默认5分钟
public function __construct($cache) {
$this->cache = $cache;
}
/**
* 获取或缓存API数据
*/
public function remember($key, $callback, $ttl = null) {
$cacheKey = md5($key);
// 1. 检查缓存
if ($data = $this->cache->get($cacheKey)) {
return $data;
}
// 2. 调用第三方API
try {
$data = call_user_func($callback);
// 3. 缓存数据
$this->cache->set(
$cacheKey,
$data,
$ttl ?? $this->defaultTTL
);
return $data;
} catch (Exception $e) {
// 异常处理:降级策略
return $this->handleFailure($cacheKey, $e);
}
}
/**
* 故障降级处理
*/
private function handleFailure($key, $e) {
// 1. 尝试返回过期缓存
if ($oldData = $this->cache->get($key . ':stale')) {
return $oldData;
}
// 2. 返回默认数据
$default = $this->getDefaultResponse();
// 3. 记录错误日志
error_log("API Cache Error: {$e->getMessage()}");
return $default;
}
}
Memcached缓存(分布式场景)
基础实现
<?php
class MemcachedCache {
private $memcached;
public function __construct($servers = [['127.0.0.1', 11211]]) {
$this->memcached = new Memcached();
$this->memcached->addServers($servers);
$this->memcached->setOption(Memcached::OPT_COMPRESSION, true);
}
public function get($key) {
return $this->memcached->get($key);
}
public function set($key, $value, $ttl = 3600) {
return $this->memcached->set($key, $value, $ttl);
}
}
最佳实践策略
缓存降级策略
<?php
class CacheStrategy {
// 阶梯缓存时间
const CACHE_TIERS = [
'high' => 60, // 高频率更新:1分钟
'medium' => 300, // 中频率更新:5分钟
'low' => 3600 // 低频率更新:1小时
];
// 根据接口类型选择缓存策略
public function getCacheTTL($apiType) {
switch ($apiType) {
case 'weather':
return self::CACHE_TIERS['medium'];
case 'stock':
return self::CACHE_TIERS['high'];
case 'country_code':
return self::CACHE_TIERS['low'];
default:
return 600; // 10分钟默认
}
}
}
双重缓存机制
<?php
class DualCache {
private $local; // 本地文件缓存
private $remote; // Redis缓存
public function __construct() {
$this->local = new FileCache();
$this->remote = new RedisCache();
}
public function get($key) {
// 1. 先查本地缓存(最快)
if ($data = $this->local->get($key)) {
return $data;
}
// 2. 再查Redis缓存
if ($data = $this->remote->get($key)) {
// 同步到本地
$this->local->set($key, $data, 60);
return $data;
}
return false;
}
public function set($key, $value, $ttl = 300) {
// 同时写入两级缓存
$this->remote->set($key, $value, $ttl);
$this->local->set($key, $value, min($ttl, 60));
}
}
缓存穿透防护
<?php
class CachePenetrationProtection {
public function getWithProtection($key, $callback, $ttl = 300) {
// 1. 使用布隆过滤器快速判断
if (!$this->bloomFilter->exists($key)) {
return null;
}
// 2. 互斥锁防止缓存击穿
$lockKey = "lock:{$key}";
if ($this->cache->get($key) === false) {
if ($this->lock($lockKey)) {
try {
$data = call_user_func($callback);
$this->cache->set($key, $data, $ttl);
return $data;
} finally {
$this->unlock($lockKey);
}
}
}
return $this->cache->get($key);
}
}
框架集成方案
Laravel示例
// config/cache.php
'api_cache' => [
'driver' => 'redis',
'connection' => 'default',
'prefix' => 'api_',
],
// 使用缓存
$weather = Cache::store('api_cache')->remember('weather', 300, function () {
return Http::get('https://api.weather.com')->json();
});
ThinkPHP示例
use think\facade\Cache;
// 配置
Cache::store('redis')->set($key, $data, 300);
// 获取
if (Cache::has($key)) {
return Cache::get($key);
}
缓存清理策略
<?php
class CacheCleaner {
// 定时清理过期缓存
public function cleanExpired() {
$files = glob('/tmp/cache/*.cache');
foreach ($files as $file) {
if (filemtime($file) + 3600 < time()) {
unlink($file);
}
}
}
// 按前缀批量清除
public function cleanByPrefix($prefix) {
$keys = $this->redis->keys("{$prefix}*");
if (!empty($keys)) {
$this->redis->del($keys);
}
}
// 缓存预热(加载常用数据)
public function warmup($apiList) {
foreach ($apiList as $api => $config) {
// 预请求并缓存
$data = $this->fetchApi($api);
$this->cache->set($api, $data, $config['ttl']);
}
}
}
建议
-
选择原则:
- 单机项目:文件缓存即可
- 中等项目:Redis
- 高并发:Redis + 本地缓存
-
缓存时间:
- 动态数据:30秒-5分钟
- 静态数据:1-24小时
- 极少变化:7天以上
-
异常处理:
- 必须包含降级策略
- 记录缓存失败日志
- 设置合理的过期时间
这样既保证了数据新鲜度,又提高了系统稳定性。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播