ifixit/matryoshka

PHP 缓存库


README

Build Status HHVM Status

Matryoshka 是一个基于嵌套组件(如俄罗斯套娃)的 PHP 缓存库。

动机

PHP 客户端库为 Memcached 服务器提供了相当低级别的访问。Matryoshka 增加了一些便利函数,以简化客户端库未涵盖的常见操作。大部分功能是通过嵌套 Backend 提供的。例如,通过在 Prefix 后端内嵌套现有的 Backend 来实现缓存键的前缀。这种理念导致非常模块化的组件,易于替换和测试。

该概念用于支持键前缀、禁用 get/set/delete 操作、在层次结构中定义缓存回退、在可清除的作用域中存储值以及记录统计信息。

后端

APCu

使用 APCu php 扩展 在共享内存段中缓存值(可供所有进程使用)。

$cache = new Matryoshka\APCu();
$cache->set('key', 'value');
$value = $cache->get('key');

Ephemeral

在本地内存数组中缓存值,该数组在 PHP 进程的持续时间内有效。

$cache = new Matryoshka\Ephemeral();
$cache->set('key', 'value');
$value = $cache->get('key');

Enable

一个包装器,允许 禁用 getsetdelete 操作。当操作被禁用时,底层后端不会被修改或访问,并返回 false

$cache = new Matryoshka\Enable($backend = (new Matryoshka\Ephemeral()));
$cache->getsEnable = false;
$cache->get('key'); // Always results in a miss.

ExpirationChange

使用回调修改所有过期时间。这允许随机化或缩放过期时间以减少错过风暴或提高命中率。

$changeFunc = function($expiration) {
   // Double all expiration times.
   return $expiration * 2;
};
$cache = new Matryoshka\ExpirationChange($backend, $changeFunc);
$cache->set('key', 'value', 10); // Results in an expiration time of 20.

KeyFix

通过缩短较长的键到指定的长度以下,并去除任何指定的无效字符来修复有问题的键。它通过使用 md5 将违规键散列成等长度的字母数字字符串来完成此操作。

$cache = new Matryoshka\KeyFix(
   new Matryoshka\Ephemeral(),
   $maxLength = 50,
   $invalidChars = " \n"
);

// Gets converted to: `2552e62135d11e8d4233e2a51868132e`
$cache->get("long_key_that_needs_to_be_shortened_by_just_a_little_bit");

// Gets converted to: `6c4421388643338490f9c2c895af4fec`
$cache->get("key with bad chars like spaces");

KeyShorten

通过缩短较长的键来确保所有键的长度最多为指定的长度。长键通过在字符串末尾使用 md5 来缩短,以确保具有公共前缀的长字符串不会映射到相同的键。

应使用此 KeyFix,而不是两者都使用。KeyFix 处理长键和坏字符,使其成为不必要的附加功能。

$cache = new Matryoshka\KeyShorten(
   new Matryoshka\Ephemeral(),
   $maxLength = 50
);

// Gets converted to: `long_key_that_need2552e62135d11e8d4233e2a51868132e`
$cache->get("long_key_that_needs_to_be_shortened_by_just_a_little_bit");

Prefix

使用字符串为所有键添加前缀。

$cache = new Matryoshka\Prefix(new Matryoshka\Ephemeral(), 'prefix-');
// The key ends up being "prefix-key".
$cache->set('key', 'value');
$value = $cache->get('key');

Stats

记录操作的计数和计时,用于指标。

$cache = new Matryoshka\Stats(new Matryoshka\Ephemeral());
$cache->set('key', 'value');
$value = $cache->get('key');
var_dump($cache->getStats());
// array(
//    'get_count' => 1,
//    'get_time' => 0.007,
//    'set_count' => 1
//    'set_time' => 0.008,
//    ...
// )

Hierarchy

将缓存设置为层次结构,以便优先考虑较快的缓存,较慢的缓存填充较快的缓存。

注意:由于一些可能出乎意料的行为,此后端目前处于实验性状态。

$cache = new Matryoshka\Hierarchy([
   new Matryoshka\Ephemeral(),
   Matryoshka\Memcached::create(new Memcached('localhost')),
   Matryoshka\Memcached::create(new Memcached($cacheServers)),
]);

// This misses the first two caches (array and local memcached) but hits the
// final cache. The retrieved value is then set in the local memcache as well
// as the memory array so subsequent requests can be fulfilled faster.
$value = $cache->getAndSet('key', function() {
   return 'value';
}, 3600);
// This is retrieved from the memory array without going all the way to
// Memcached.
$value = $cache->getAndSet('key', function() {
   return 'value';
}, 3600);

Local

将指定后端的所有值缓存到本地数组中,以便可以更快地满足对相同键的后续请求。

$cache = new Matryoshka\Local(new Memcached());

这是它的一个更快版本

$cache = new Matryoshka\Hierarchy([
   new Matryoshka\Ephemeral(),
   Matryoshka\Memcached::create(new Memcached('localhost'))
]);

Scope

在作用域中缓存值,该作用域可以删除以使作用域下的所有缓存条目失效。

$cache = new Matryoshka\Scope(new Matryoshka\Ephemeral(), 'scope');
$cache->set('key', 'value');
$value = $cache->get('key'); // => 'value'
$cache->deleteScope();
// This results in a miss because the scope has been deleted.
$value = $cache->get('key'); // => false

MultiScope

使用多个作用域来存储键。在一个后端中存储作用域或作用域,在另一个后端中存储作用域值。这主要允许在一个共享但较慢的访问后端中存储作用域(以便易于删除),同时将值存储在本地且较快的后端中,以便快速访问。

$scope1 = new Matryoshka\Scope($remoteMemcached, 'scope1');
$scope2 = new Matryoshka\Scope($remoteMemcached, 'scope2');
$multiScope = new Matryoshka\MultiScope($localMemcached, [
   $scope1,
   $scope2
]);
// Stores the value on the local memcached backend but scope it to
// scope1 and scope2 which are stored on the remote memcache instance.
$multiScope->set('key', 'value');
$scope1->deleteScope();
// This results in a miss because one of the scopes has been deleted.
$value = $multiScope->get('key');

便利函数

getAndSet

get()set() 的包装器,它使用读取通过回调来生成丢失的值。

$cache = new Matryoshka\Ephemeral();
// Calls the provided callback if the key is not found and sets it in the cache
// before returning the value to the caller.
$value = $cache->getAndSet('key', function() {
   return 'value';
});

getAndSetMultiple

getMultiple() 的包装器,它使用回调批量生成值以填充缓存。

$cache = new Matryoshka\Ephemeral();
$keys = [
   'key1' => 'id1',
   'key2' => 'id2'
];
// Calls the provided callback for any missed keys so the missing values can be
// generated and set before returning them to the caller. The values are
// returned in the same order as the provided keys.
$values = $cache->getAndSetMultiple($keys, function($missing) {
   // Use the id's to fill in the missing values.
   foreach ($missing as $key => $id) {
      if ($id == 'id1') {
         $value = 'value1';
      } else if ($id == 'id2') {
         $value = 'value2';
      }

      $missing[$key] = $value;
   }

   // Return the new values to be cached and merged with the hits.
   return $missing;
});

许可证

The MIT License (MIT)

Copyright (c) 2014 iFixit

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the Software), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.