phpixie/cache

PHPixie 缓存库

3.3.1 2019-12-25 09:07 UTC

This package is auto-updated.

Last update: 2024-08-30 14:19:16 UTC


README

PHPixie 缓存库

Build Status Author Source Code Software License

PHPixie 缓存组件支持 PSR-6 和 PSR-16 标准,并增加了一些有用的特性。

初始化

如果您使用 PHPixie 框架,组件可以通过您的构建器访问,并在 /assets/config/cache.php 中配置。

$cache = $builder->components->cache();

像所有其他 PHPixie 组件一样,您可以在不使用框架的情况下使用它,在这种情况下,您可以像这样初始化它

$slice = new \PHPixie\Slice();
$config = $slice->arrayData([
     // configuration
    'default' => [
         'driver' => 'memory'
    ]
]);


// Optional dependency if you want to use file cache.
// This defines the root folder for file based drivers.
$filesystem = new \PHPixie\Filesystem();
$root = $filesystem->root('/tmp/cache/');

$cache = new \PHPixie\Cache($config, $root);

配置

类似于您配置数据库连接,您可以使用可用的驱动程序定义多个存储配置: voidmemoryphpfilememcachedredis

return [
    'default' => [
        // Doesn't store anything
        'driver' => 'void'
    ],

    'second' => [
        // Stores in a simple array
        'driver' => 'memory',

        /* Optional */

        /**
         * Default lifetime,
         * can be either number of seconds
         * or a DateInterval value, e.g. 'P1D' is one day.
         * Default is null, which is to store forever
         */
        'defaultExpiry' => 10,

        /**
         * A number between 1 and 1000 that
         * defines the frequency of garbage collection.
         * Defaults to 10, so 1% of all cache queries will
         * result in garbage collection to be run.
         */
        'cleanupProbability' => 10
    ],

    'third' => [
        // Values stored as .php files in folder
        'driver' => 'phpfile',

        // Relative to the /assets/cache folder
        'path'   => 'third',

        /* Optional */
        'defaultExpiry' => null,
        'cleanupProbability' => 10
    ],

    'fourth' => [
        'driver'  => 'memcached',

        /**
         * Same argument as to the Memcached::addServers() method,
         * but the port and weight parameters can be omitted and
         * default to 11211 and 1 respectively
         */
        'servers' => [
            ['127.0.0.1']
        ],

        /* Optional */
        'defaultExpiry' => null
    ],

    'fifth' => [
        'driver'  => 'redis',

        // Same argument as to the Predis\Client constructor
        'connection' => array(
            'scheme' => 'tcp',
            'host'   => '127.0.0.1',
            'port'   => 6379
        ),

        /* Optional */
        'defaultExpiry' => null
    ]
];

使用方法

如前所述,PHPixie 缓存支持 PSR-6 和新的简化版 PSR-16。您将主要使用 PHPixie\Cache\Pool 接口的实例。

namespace PHPixie\Cache;

use PHPixie\Cache\Pool\Prefixed;
use Psr\Cache\CacheItemPoolInterface;
use Psr\SimpleCache\CacheInterface;

// Inherits both PSR-6 and PSR-16
interface Pool extends CacheItemPoolInterface, CacheInterface
{
    /**
     * Creates a PSR-6 Item instance without trying to retrieve it from cache
     * @param string $key
     * @param mixed $value
     * @return Item
     */
    public function createItem($key, $value = null);

    /**
     * Creates a namespaced prefix pool.
     * We'll cover this later.
     * @param string $prefix
     * @return Prefixed
     */
    public function prefixedPool($prefix);
}

一些示例

// Getting one of the defined storages
$storage = $cache->storage('second');

// PSR-6
public function getFairies()
{
    $item = $this->storage->getItem('fairies');
    if (!$item->isHit()) {
        $fairies = $this->generateFairies();
        $item->set($fairies);
        $item->expiresAfter(100);
        $this->storage->save($item);
    }
    return $item->get();
}

// PSR-16
public function getFairies()
{
    $fairies = $this->storage->get('fairies');
    if($fairies === null) {
         $fairies = $this->buildFairies();
         $this->storage->set('fairies', $fairies, 100);
    }
    return $fairies;
}

在这里重写这些 PSR 的所有使用示例是没有意义的,这些 PSR 已经有很好的文档。如 deleteclear 等附加方法非常直观,很容易在 PSR 文档和 IDE 提示中找到。让我们专注于一些独特的功能。

前缀池

当应用程序的多个部分使用相同的缓存存储时,常见的做法是使用前缀。您多久看到这样的代码

$key = 'article-'.$id;
$article = $cache->get($key);

如果这些实体被缓存在不同部分的应用程序中,您必须确保始终使用相同的前缀,或者甚至将此逻辑抽象成一个单独的服务。PHPixie Cache 使用前缀池来自动对存储进行前缀,从而解决了这个问题

$storage = $cache->storage('default');
$articlesPool = $storage->prefixedPool('article');

$articlesPool->set($article->id, $article->html());

// same as
$storage ->set('article.'.$article->id, $article->html());

如您所料,这样的池也实现了与存储相同的 PHPixie\Cache\Pool 接口,并且本身也可以进行前缀,从而创建一个层次结构。它们可以用来为不同的实体定义不同的池,并且也使得将来在需要时轻松地将一些池切换到实际的独立存储变得容易。例如,您可以从一个缓存存储和多个前缀池开始,并在应用程序增长时轻松地扩展。

无需存储的简单使用

本身 PHPixie\Cache 类也实现了 Pool 接口,并将请求代理到默认的缓存存储。这使得组件在只有一个缓存存储的应用程序中更容易使用。

// instead of
$cache->storage('default')->get('fairy');

// just use
$cache->get('fairy');

不哈希键

大多数文件系统缓存对键进行哈希以生成合适的文件名,这是为了保护您免受使用文件系统不支持字符的键的影响。实际上,大多数人仍然使用字母数字缓存键,对这些键进行哈希并没有真正的价值,但会使缓存文件难以检查,并略微影响应用程序的性能。PHPixie Cache 使用原始键作为文件名,尽管如果需要可以轻松引入哈希。

优化的文件缓存

大多数缓存库将值与过期时间戳一起序列化以存储在文件缓存中。这种方法有两个缺点:每次读取值时都必须反序列化,这会影响性能,当频繁使用时;此外,仅检查缓存是否尚未过期就必须反序列化整个文件,如果之后实际未使用值,则这是一种浪费。那么 PHPixie Cache 是如何解决这些问题的?让我们看看一个缓存的文件示例

<?php /*1483041355*/
return array(1,2,3);

第一行包含一个带有过期时间的注释,可以通过只阅读这一行来简单地检查,而忽略文件的其他部分。此外,缓存以PHP代码的形式存储,通过使用include运算符检索。这意味着您的opcache将缓存它,而不是每次请求时都从磁盘读取文件。这种方法对于只写一次、频繁读取的场景(如配置缓存等)特别出色,实际上可以优于其他存储方式。

贡献和添加驱动程序

由于PHPixie的社会组件在社区的帮助下添加了新的提供者,我决定添加一个关于如何贡献和向PHPixie Cache添加自己的存储驱动程序的简单指南。

  1. 添加一个名为PHPixie\Cache\Drivers\Type\YourDriver的类,它继承自PHPixie\Cache\Drivers\Driver
  2. PHPixie\Cache\Builder::$driverMap中注册它。
  3. 创建一个名为PHPixie\Tests\Cache\Driver\YourDriverTest的测试类,它继承自PHPixie\Tests\Cache\DriverTest
  4. 编辑.travis.ymlcomposer.json,添加必要的依赖项和包,以便在Travis CI上运行测试。
  5. 提交拉取请求 ;)

当然,我们的聊天室也愿意帮助解决您遇到的问题。