react/cache

ReactPHP 的异步、基于 Promise 的缓存接口

维护者

详细信息

github.com/reactphp/cache

源代码

问题

资助包维护!
Open Collective

安装量: 41,466,923

依赖: 45

建议者: 1

安全: 0

星标: 390

关注者: 12

分支: 21

开放问题: 2

v1.2.0 2022-11-30 15:59 UTC

This package is auto-updated.

Last update: 2024-09-03 13:21:37 UTC


README

CI status installs on Packagist

异步、基于 PromiseReactPHP 缓存接口。

开发版本:此分支包含即将推出的 v3 版本的代码。要查看当前稳定版本 v1 的代码,请查看 1.x 分支

即将推出的 v3 版本将是此包的发展方向。然而,我们仍将积极支持 v1,以帮助那些尚未升级到最新版本的用户。有关更多信息,请参阅安装说明

缓存组件提供了一个基于 PromiseCacheInterface 以及该接口的内存 ArrayCache 实现。这允许消费者对接口进行类型提示,并允许第三方提供替代实现。此项目受到了 PSR-16: 缓存库的通用接口 的很大启发,但使用了更适合异步、非阻塞应用程序的接口。

目录

用法

CacheInterface

CacheInterface 描述了此组件的主要接口。这允许消费者对接口进行类型提示,并允许第三方提供替代实现。

get()

可以使用 get(string $key, mixed $default = null): PromiseInterface<mixed> 方法从缓存中检索项目。

此方法在成功时解析为缓存的值,或者在找不到项目或发生错误时解析为给定的 $default 值。同样,已过期的缓存项(一旦生存时间到期)被视为缓存未命中。

$cache
    ->get('foo')
    ->then('var_dump');

此示例获取键 foo 的值,并将其传递给 var_dump 函数。您可以使用 promises 提供的任何组合。

set()

可以使用 set(string $key, mixed $value, ?float $ttl = null): PromiseInterface<bool> 方法将项目存储到缓存中。

此方法在成功时解析为 true,或者在发生错误时解析为 false。如果缓存实现必须通过网络来存储它,它可能需要一些时间。

可选的 $ttl 参数设置此缓存项的最大生存时间(以秒为单位)。如果省略此参数(或 null),则项目将根据底层实现的支持时间保留在缓存中。尝试访问已过期的缓存项将导致缓存未命中,请参阅get() 以获取更多信息。

$cache->set('foo', 'bar', 60);

此示例最终将键 foo 的值设置为 bar。如果它已存在,则将其覆盖。

此接口不强制执行特定的TTL分辨率,因此如果依赖于毫秒级或更精确的高精度,可能需要特别小心。缓存实现应尽可能工作,除非有其他说明,否则至少提供秒级精度。许多现有的缓存实现已知提供微秒或毫秒级精度,但通常不建议依赖于这种高精度。

此接口建议如果可用,缓存实现应使用单调时间源。由于单调时间源默认仅从PHP 7.3开始提供,缓存实现可能回退到使用系统时间。虽然这不会影响许多常见用例,但对于依赖于高时间精度或系统易受不连续时间调整(时间跳跃)的程序来说,这是一个重要的区别。这意味着如果您存储一个30秒TTL的缓存项,然后调整系统时间提前20秒,缓存项仍然应在30秒后过期。

delete()

可以使用delete(string $key): PromiseInterface<bool>方法从缓存中删除一个项目。

此方法在成功时解析为true或在发生错误时解析为false。当在缓存中没有找到$key对应的项时,它也解析为true。如果缓存实现必须通过网络删除,可能需要一段时间。

$cache->delete('foo');

此示例最终将键foo从缓存中删除。与set()一样,这可能不会立即发生,并返回一个承诺以提供保证是否已从缓存中删除项目。

getMultiple()

可以使用getMultiple(string[] $keys, mixed $default = null): PromiseInterface<array>方法通过其唯一键检索多个缓存项。

此方法在成功时解析为一个包含缓存值的数组,或在找不到项或发生错误时解析为给定的$default值。同样,已过期的缓存项(一旦TTL过期)被视为缓存未命中。

$cache->getMultiple(['name', 'age'])->then(function (array $values): void {
    $name = $values['name'] ?? 'User';
    $age = $values['age'] ?? 'n/a';

    echo $name . ' is ' . $age . PHP_EOL;
});

此示例获取nameage键的缓存项并打印一些示例输出。您可以使用承诺提供的任何组合。

setMultiple()

可以使用setMultiple(array $values, ?float $ttl = null): PromiseInterface<bool>方法使用可选的TTL持久化缓存中的键值对集。

此方法在成功时解析为 true,或者在发生错误时解析为 false。如果缓存实现必须通过网络来存储它,它可能需要一些时间。

可选的$ttl参数设置这些缓存项的最大存活时间(秒)。如果省略此参数(或为null),这些项将保留在缓存中,直到底层实现支持。尝试访问已过期的缓存项会导致缓存未命中,有关更多信息,请参阅getMultiple()

$cache->setMultiple(['foo' => 1, 'bar' => 2], 60);

此示例最终设置一系列值 - 键foo映射到值1和键bar映射到值2。如果某些键已存在,它们将被覆盖。

deleteMultiple()

可以使用setMultiple(string[] $keys): PromiseInterface<bool>方法在单个操作中删除多个缓存项。

此方法在成功时解析为true或在发生错误时解析为false。当在缓存中没有找到$keys对应的项时,它也解析为true。如果缓存实现必须通过网络删除,可能需要一段时间。

$cache->deleteMultiple(['foo', 'bar, 'baz']);

此示例最终从缓存中删除键foobarbaz。与setMultiple()一样,这可能不会立即发生,并返回一个承诺以提供保证是否已从缓存中删除项目。

clear()

可以使用clear(): PromiseInterface<bool>方法清除整个缓存。

此方法在成功时解析为true或在发生错误时解析为false。如果缓存实现必须通过网络删除,可能需要一段时间。

$cache->clear();

本示例最终将删除缓存中的所有键。与deleteMultiple()类似,这可能不会立即发生,并且会返回一个承诺来确保是否已从缓存中删除所有项。

has()

可以使用has(string $key): PromiseInterface<bool>方法来确定一个项目是否存在于缓存中。

此方法在成功时将解析为true,在找不到项目或发生错误时将解析为false。同样,过期的缓存项(一旦生存时间过期)被视为缓存未命中。

$cache
    ->has('foo')
    ->then('var_dump');

此示例检查键foo的值是否在缓存中设置,并将结果传递给var_dump函数。您可以使用承诺提供的任何组合。

注意:建议仅在缓存预热类型用途中使用has(),不要在您的实际应用程序操作中用于get/set,因为这个方法可能会发生竞态条件,即has()返回true后,另一个脚本可以立即删除它,从而使您的应用程序状态过时。

ArrayCache

ArrayCache提供了CacheInterface的内存实现。

$cache = new ArrayCache();

$cache->set('foo', 'bar');

其构造函数接受一个可选的?int $limit参数,用于限制存储在LRU缓存中的最大条目数。如果您向此实例添加更多条目,它将自动处理删除最少最近使用的条目(LRU)。

例如,此片段将覆盖第一个值,并仅存储最后两个条目

$cache = new ArrayCache(2);

$cache->set('foo', '1');
$cache->set('bar', '2');
$cache->set('baz', '3');

此缓存实现已知在使用PHP 7.3之前的任何版本时依赖于系统时间来安排未来的缓存过期时间,因为从PHP 7.3开始才提供单调时间源(hrtime())。虽然这不会影响许多常见用例,但对于依赖于高时间精度或受到不连续时间调整(时间跳跃)影响的系统,这是一个重要的区别。这意味着如果您在PHP < 7.3上存储了一个TTL为30秒的缓存项,然后您的系统时间向前调整了20秒,该缓存项可能在10秒后过期。有关更多详细信息,请参阅set()

常见用法

回退获取

缓存的一个常见用例是尝试获取缓存值,如果未找到,则从原始数据源检索它。以下是一个示例

$cache
    ->get('foo')
    ->then(function ($result) {
        if ($result === null) {
            return getFooFromDb();
        }
        
        return $result;
    })
    ->then('var_dump');

首先尝试检索foo的值。注册了一个回调函数,当结果值为null时将调用getFooFromDbgetFooFromDb是一个函数(可以是任何PHP调用者),如果键不存在于缓存中,则会被调用。

getFooFromDb可以通过返回从数据库(或任何其他数据源)获取实际值的承诺来处理丢失的键。因此,此链将正确回退,并在两种情况下都提供值。

回退获取和设置

在扩展回退获取示例时,通常您希望在从数据源获取值后将其设置在缓存中。

$cache
    ->get('foo')
    ->then(function ($result) {
        if ($result === null) {
            return $this->getAndCacheFooFromDb();
        }
        
        return $result;
    })
    ->then('var_dump');

public function getAndCacheFooFromDb()
{
    return $this->db
        ->get('foo')
        ->then([$this, 'cacheFooFromDb']);
}

public function cacheFooFromDb($foo)
{
    $this->cache->set('foo', $foo);

    return $foo;
}

通过使用链,您可以轻松地有条件地缓存从数据库中检索的值。

安装

安装此库的推荐方法是通过Composer。您是Composer的新手吗?新用户?

一旦发布,此项目将遵循SemVer。目前,这将安装最新开发版本

composer require react/cache:^3@dev

有关版本升级的详细信息,请参阅变更日志

本项目的目标是运行在任何平台上,因此不需要任何PHP扩展,并且支持在PHP 7.1到当前最新的PHP 8+上运行。强烈建议为此项目使用最新支持的PHP版本。

测试

要运行测试套件,您首先需要克隆此仓库,然后通过Composer安装所有依赖项(请访问Composer官网)

composer install

要运行测试套件,请进入项目根目录并执行

vendor/bin/phpunit

此外,我们使用PHPStan的最高级别来确保项目中的类型安全

vendor/bin/phpstan

许可

采用MIT许可证,请参阅许可证文件