aol/offload

此包已被废弃且不再维护。未建议替代包。

简化缓存的PHP任务:后台刷新、最后已知良好状态和单写者。

安装次数: 13,120

依赖者: 0

建议者: 0

安全: 0

星标: 10

关注者: 21

分支: 2

开放问题: 0

类型:项目

2.2.1 2018-02-01 16:43 UTC

README

简化缓存的PHP任务:后台刷新、最后已知良好状态和单写者。

Build Status Coverage Status Code Climate Latest Stable Version Latest Unstable Version License

示例

$offload = new OffloadManager(/* ... */);

// Fetch a result and repopulate it if necessary.
$data = $offload->fetch('task-key', function () {

  // Perform a time consuming task...
  return $data;

})->getData();

这将运行后台任务并缓存返回的 $datatask-key 下。如果再次请求数据,如果它在缓存中,则立即返回;如果缓存已过时,则进行数据恢复。

这是如何工作的?

Offload 使用两种时间范围来缓存数据:新鲜和过时。这些 TTL 可以使用选项进行控制,请参阅 Offload 选项

  • 新鲜(缓存命中):立即返回数据,无需重新填充。
  • 过时(缓存命中,过时):立即返回数据,并排队进行重新填充。
  • 无数据(缓存未命中):强制立即运行重新填充,然后将数据缓存并返回。

Offload 使用任务队列来跟踪需要重新填充的过时缓存命中。当调用 $offload->drain() 时,将运行所有任务并重新填充缓存。最好在请求完成后这样做,这样重新填充缓存的开销就不会干扰快速向客户端返回响应。请参阅 清空 Offload 队列

OffloadManager 可以接受任何实现 OffloadCacheInterface 的缓存存储。

独占任务

默认情况下,任务以 exclusive 方式运行。可以使用选项更改此行为,请参阅 Offload 选项

独占任务重新填充意味着对于给定的键,将始终只有一个并发过时重新填充。这避免了当缓存项过期时发生的 重新填充缓存的竞争

OffloadManager 使用锁实现来提供此功能,并且可以接受任何实现 OffloadLockInterface 的锁。

初始化

以下是一个使用 memcached 实例进行缓存和使用 redis 实例进行锁定的示例

// Setup a cache.
$cache = new OffloadCacheMemcached($memcached_instance);

// Setup a lock.
$lock = new OffloadLockRedis($predis_instance);

// Default options for offload manager:
$default_options = [
  'ttl_fresh'          => 5,    // Cache time in seconds
  'ttl_stale'          => 5,    // Stale cache time in seconds
  'exclusive'          => true, // Whether to run tasks exclusively by key (no concurrent repopulates for the same key)
  'background'         => true, // Whether to run tasks in the background
  'background_timeout' => 5,    // Timeout for exclusive background repopulates in seconds
];

// Create the offload manager.
$offload = new OffloadManager($cache, $lock, $default_options);

清空 Offload 队列

为了正确地清空 Offload 队列,最好是设置 PHP 关闭处理程序。这确保 Offload 任务将在请求结束时始终运行。示例

// ...

register_shutdown_function(function () use ($offload) {
  if ($offload->hasWork()) {

    // Flush all buffers.
    while (ob_get_level()) {
      ob_end_flush();
    }
    flush();

    // End the request if possible (under PHP FPM).
    if (function_exists('fastcgi_finish_request')) {
      fastcgi_finish_request();
    }

    // Run all tasks in the queue.
    $offload->drain();
  }
});

延迟任务

Offload 支持从重新填充可调用的返回延迟任务。这允许在清空 Offload 队列时并行运行多个任务。

例如,使用 Guzzle 异步请求

$data = $offload->fetch('task-key', function () {

  // ...

  $promise = $guzzle_client->getAsync('http://www.example.com');

  return new OffloadDeferred([$promise, 'wait']);

})->getData();

OffloadDeferred 类接受一个将等待结果的单一可调用。在上面的示例中,$promise->wait() 等待 HTTP 请求完成并返回结果。

重新填充可调用可以返回任何实现 OffloadDeferredInterface 的类,因此您可以创建用于自定义异步处理的适配器。

API

OffloadManager 实现 OffloadManagerInterface 并公开以下方法

OffloadManager
fetch(...) 从缓存中获取数据并在必要时进行重新填充。
fetchCached(...) 与带有特定新鲜缓存TTL的fetch(...)相同。
queue(...) 将任务排队运行。
queueCached(...) queue(...)相同,但带有特定的新鲜缓存TTL。
hasWork() 是否离载管理器有工作。
drain() 排空离载管理器任务队列。
getCache() 用于手动与缓存交互的对象。

有关上述方法的更多详细信息,请参阅下文。

有关可以提供的$options的更多信息,请参阅离载选项。有关返回的OffloadResult详细信息的更多信息,请参阅离载结果

获取数据

fetch

fetch($key, callable $repopulate, array $options = []): OffloadResult

检查缓存中给定$key的数据。如果数据在缓存中,则立即返回它。如果数据已过时,则安排在离载管理器排空时运行重新填充。

$result = $offload->fetch($key, function () {
  // Perform long running task...
  return $data;
});

fetchCached

fetchCached($key, $ttl_fresh, callable $repopulate, array $options = []): OffloadResult

fetch相同。以下内容等效

$result = $offload->fetch($key, $repopulate, ['ttl_fresh' => 5]);
// is the same as:
$result = $offload->fetchCached($key, 5, $repopulate);

排队任务

queue

queue($key, callable $repopulate, array $options = []): void

将重新填充任务排队运行。不检查缓存。接受与fetch相似的选项。

queueCached

queueCached($key, $ttl_fresh, callable $repopulate, array $options = []): void

queue相同。以下内容等效

$result = $offload->queue($key, $repopulate, ['ttl_fresh' => 5]);
// is the same as:
$result = $offload->queueCached($key, 5, $repopulate);

Fetch/Queue 参数

选项 类型
$key string 要存储的数据的键。
$ttl_fresh float 缓存数据的刷新TTL(以秒为单位)。这仅提供给fetchCachedqueueCached
$repopulate callable 一个可调用的函数,返回用于重新填充缓存的数据。
$options array 离载选项(见离载选项)。

将结果标记为“坏”

有时从重新填充返回的结果状态不佳,不应缓存

离载管理器为重新填充的可调用函数提供了一个OffloadRun实例,可用于将结果标记为坏,例如

$offload->fetch($key, function (OffloadRun $run) {

  // Get some data from a service...
  $object = $this->service->get($arguments);
  if (!$object->isValid()) {

    // If the data returned is not valid, mark the result as bad.
    // This will tell the offload manager *not to cache* the data.
    $run->setBad();

  }

});

离载选项

离载选项以数组形式提供,例如

$options = [
  'ttl_fresh'  => 5,
  'ttl_stale'  => 10,
  'background' => true,
  // ...
];
$result = $offload->fetch($key, function () { /* ... */ }, $options);
选项
ttl_fresh 将数据视为新鲜并缓存的时间(以秒为单位)。新鲜数据不会重新填充。默认值为0
ttl_stale 将数据视为陈旧并缓存的时间(以秒为单位)。当获取时,陈旧数据将被重新填充。此值是添加到ttl_fresh的,以获得总缓存时间。默认值为5
exclusive 是否单独运行任务(同一键的其他任务不能同时运行)。默认值为true
background 是否在后台运行任务。这意味着它将等待离载管理器排空,而不是立即重新填充。默认值为true
background_timeout 以秒为单位超时独占后台任务的时长。默认值为5
background_release_lock 是否在卸载的任务完成时立即释放重新填充锁。默认为 true。如果设置为 false,卸载将等待后台超时完成后再允许新的重新填充。

卸载结果

OffloadResult 类提供了以下方法

OffloadResult
getData() 重新填充可调用函数返回的数据。
isFromCache() 数据是否来自缓存。
getExpireTime() 缓存中的数据过期时间(Unix时间秒)。
getStaleTime() 数据在秒内过期的时长。如果值为负数,则表示数据距离过期还有多长时间。
isStale() 结果是否来自缓存,但已过期。

编码器

默认情况下,卸载将使用 OffloadEncoderStandard(它执行简单的PHP序列化)来编码和解码存储在缓存中的数据。您可以通过实现 OffloadEncoderInterface 并在 OffloadManagerCache 实例上设置编码器来更改此设置。

class CustomEncoder implements OffloadEncoderInterface
{
    // ...

    public function encode($object)
    {
        // ... Encode the value ...
        return $string_value;
    }

    public function decode($string)
    {
        // ... Decode the value ...
        return $object_value;
    }
}

// ...

$offload = new OffloadManager(/* ... */);

// Change the encoder.
$offload->getCache()->setEncoder(new CustomEncoder(/* ... */));

默认情况下,卸载将使用您设置的编码器来 解码。您可以通过调用 setDecoder 来更改解码以使用单独的实例。

$offload->getCache()->setEncoder(new FooEncoder(/* ... */));
$offload->getCache()->setDecoder(new BarEncoder(/* ... */));

加密

Offload附带了一个利用AES-256加密的加密编码器。它包装了任何实现了 OffloadEncoderInterface 的其他编码器。要使用它,只需将其设置为卸载缓存的编码器即可。

// Get the base encoder.
$base_encoder = $offload->getCache()->getEncoder();

// Wrap it with an encrypting encoder.
$encrypting_encoder = new OffloadEncoderEncryptedAes256(
    $base_encoder,
    // The key ID for the encryption.
    'foo',
    // Secret keys by ID. This enables key cycling.
    [
        'foo' => 'my_secret_key'
    ]
)

$offload->getCache()->setEncoder($encrypting_encoder);

自定义加密

您可以通过扩展抽象类 OffloadEncoderEncrypted 来实现自定义加密。

class CustomEncryptionEncoder extends OffloadEncoderEncrypted
{
    // ...

    protected function encrypt($string, $key)
    {
        // ... return encrypted string ..
    }

    protected function decrypt($string, $key)
    {
        // ... return decrypted string ..
    }
}

许可证

BSD-3-Clause