Класс-сервис для кэширования данных на PHP
Всем привет, хотел бы поделиться небольшой своей наработкой — классом, который использую в качестве сервиса для кэширования данных в PHP.
В приведенном примере в качестве хранилища для кэша используется memcached. Однако, данный класс довольно легко модифицировать и использовать в качестве хранилища хоть жёсткий диск, предварительно сериализовав кэшируемые данные, если это требуется. Сам класс создаётся другим-классом фабрикой и используется на протяжении всей жизни приложения. Вы же можете сделать его синглтоном.
Для начала сам класс:
class Cache
{
private $_cachesTTL;
private $_realTimeStorage = [];
private $_memcached;
public function __construct(array $cachesTTL)
{
$this->_cachesTTL = $cachesTTL;
$this->_memcached = new \Memcached();
$this->_memcached->addServer('localhost', 11211);
}
public function set(string $key, $value)
{
$this->_realTimeStorage[$key] = $value;
$ttl = $this->_getTTL($key);
$this->_memcached->set($key, $value, $ttl);
}
public function get(string $key)
{
if (isset($this->_realTimeStorage[$key])) {
return $this->_realTimeStorage[$key];
}
return $this->_realTimeStorage[$key] = $this->_memcached->get($key);
}
public function invalidate(string $key)
{
if (isset($this->_realTimeStorage[$key])) {
unset($this->_realTimeStorage[$key]);
}
$this->_memcached->delete($key);
return $this;
}
private function _getTTL(string $key)
{
$prefix = explode(':', $key)[0];
if (!isset($this->_cachesTTL[$prefix])) {
return $this->_cachesTTL['default_ttl'];
}
return $this->_cachesTTL[$prefix];
}
}
В конструктор класса передается конфигурация, представляющая собой ассоциативный массив, в качестве ключей которого выступают названия ключей кэша, а в качестве значений — время жизни для объекта с данным ключом. Например, такой:
[
'default_ttl' => 60,
'page' => 60*60*24,
'rubrics' => 60*60*24,
'post' => 60,
'menu' => 60*60*24
]
Полный ключ объекта при этом может быть составным и отделяется от основного ключа с помощью двоеточия. Время жизни с помощью метода _getTTL($key) вычисляется по основному ключу. Например, можно сохранять в кэш разные посты, при этом время жизни для них будет одинаковым:
<?php
$cache->set('post:1', $post1);
$cache->set('post:2', $post2);
Метод get($key) возвращает либо существующее значение, либо false. Здесь, как Вы понимаете, имеется ограничение — false мы не кэшируем.
Метод invalidate($key) инвалидирует кэш по нашему запросу. Например, при обновлении какого-то объекта, когда мы не хотим тут же добавлять его в кэш.
Внутри класса есть собственное хранилище, представляющее собой массив. Живет оно в рамках одного запуска приложения. При добавлении в кэш или при извлечении его из объекта в рантайме, оно будет продублировано в это свойство. В случае моего приложения это дало прирост в скорости выполнения в районе 15 процентов. Прежде чем добавлять его себе — проверьте на реальных данных. Если данные нигде не будут использоваться повторно, то этот приём сделает только хуже.
Буду рад узнать о ваших реализациях кэширования в комментариях.
Комментарии