You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP中是否可实现类似Guava LoadingCache的带过期时间的加载式内存缓存?

PHP中是否可实现类似Guava LoadingCache的带过期时间的加载式内存缓存?

当然可以!我之前做Web项目时也碰到过一模一样的需求——不想每次都绕数据库取重复内容,就想要个像Guava LoadingCache那样,能自动过期、过期后自动从数据源刷新的缓存,省得自己写一堆重复的判断逻辑。

下面给你捋几种可行的方案,从手动实现到现成工具都有:

一、手动封装轻量版(无依赖,单请求内有效)

如果你的需求是同一次请求里避免重复查数据库,那用PHP的静态变量就能快速实现,完全不用装任何额外东西:

class SimpleLoadingCache {
    private static array $cache = [];

    /**
     * 获取缓存,不存在或过期时自动调用加载函数
     * @param string $key 缓存键
     * @param callable $loader 加载数据的回调(比如从数据库查询的逻辑)
     * @param int $ttl 过期时间,单位秒
     * @return mixed
     */
    public static function get(string $key, callable $loader, int $ttl = 300) {
        // 检查缓存是否存在且未过期
        if (isset(self::$cache[$key]) && self::$cache[$key]['expires_at'] > time()) {
            return self::$cache[$key]['value'];
        }

        // 缓存失效,调用加载函数获取新数据
        $value = $loader();
        // 存入缓存,记录过期时间
        self::$cache[$key] = [
            'value' => $value,
            'expires_at' => time() + $ttl
        ];

        return $value;
    }
}

用的时候也很简单,比如从数据库取用户列表:

$users = SimpleLoadingCache::get('user_list', function() {
    // 这里写你的数据库查询逻辑
    $pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
    $stmt = $pdo->query('SELECT * FROM users');
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}, 3600); // 1小时过期

不过要注意:这种静态变量的缓存只在当前请求周期内有效,请求结束后PHP进程释放,缓存就清空了。如果要跨请求共享缓存,得用下面的方案。

二、跨请求的内存缓存(用APCu扩展)

如果想让缓存在不同请求之间也能复用,推荐用APCu——这是PHP官方维护的用户态内存缓存扩展,数据存在内存里,速度超快,完全符合你要的“memory cache”需求。

首先得确保你装了APCu扩展(大部分服务器都默认装了,没装的话用pecl install apcu就能搞定),然后封装一个类似LoadingCache的逻辑:

class ApcuLoadingCache {
    /**
     * 获取缓存,自动加载刷新
     * @param string $key 缓存键
     * @param callable $loader 数据加载回调
     * @param int $ttl 过期时间,单位秒
     * @return mixed
     */
    public static function get(string $key, callable $loader, int $ttl = 300) {
        // 尝试从APCu取缓存
        $value = apcu_fetch($key, $success);
        if ($success) {
            return $value;
        }

        // 缓存不存在或过期,加载新数据
        $value = $loader();
        // 存入APCu并设置过期时间
        apcu_store($key, $value, $ttl);

        return $value;
    }
}

用法和之前的手动版几乎一样,而且这个缓存是跨请求的,只要服务器不重启、缓存没过期,下次请求直接用就行,完全不用碰数据库。

三、框架自带的缓存方案(如果用PHP框架的话)

要是你用Laravel、Symfony这类主流框架,那根本不用自己封装,框架早就给你做好类似的功能了:

  • 比如Laravel里的Cache::remember方法,完美对应你的需求:
    $users = Cache::remember('user_list', 3600, function() {
        return DB::table('users')->get();
    });
    
    这里3600是过期时间(秒),回调里写数据库查询逻辑,缓存过期会自动调用回调刷新。
  • Symfony的Cache组件也有类似的get方法,用ArrayAdapter(内存)或RedisAdapter都能实现带TTL的自动加载。

总的来说,不管是自己手动写轻量版,还是用现成的扩展、框架工具,都能实现和Guava LoadingCache几乎一样的效果,完全能满足你“缓存x秒后自动从数据库刷新”的需求,比直接依赖数据库缓存高效多了。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 08:24:51