react / cache
ReactPHP 的异步、基于 Promise 的缓存接口
Requires
- php: >=5.3.0
- react/promise: ^3.0 || ^2.0 || ^1.1
Requires (Dev)
- phpunit/phpunit: ^9.5 || ^5.7 || ^4.8.35
README
异步、基于 Promise 的 ReactPHP 缓存接口。
开发版本:此分支包含即将推出的 v3 版本的代码。要查看当前稳定版本 v1 的代码,请查看
1.x
分支。即将推出的 v3 版本将是此包的发展方向。然而,我们仍将积极支持 v1,以帮助那些尚未升级到最新版本的用户。有关更多信息,请参阅安装说明。
缓存组件提供了一个基于 Promise 的 CacheInterface
以及该接口的内存 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; });
此示例获取name
和age
键的缓存项并打印一些示例输出。您可以使用承诺提供的任何组合。
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']);
此示例最终从缓存中删除键foo
、bar
和baz
。与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时将调用getFooFromDb
。getFooFromDb
是一个函数(可以是任何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许可证,请参阅许可证文件。