Пулы кешей и поддерживаемые адаптеры

Пулы кешей и поддерживаемые адаптеры

Пулы кешей это логичные хранилища кешированных объектов. Они проводят все общие операции на объектах, вроде их сохранения или поиска. Пулы кешей не зависят от самой реализации кеша. Следовательно, приложения могут продолжать использовать один и тот же пул кеша, даже если основопоожный механизм кеша меняется из кеша, основанного на файловой системе, на кеш, основанный на Redis или DB.

Поиск объектов кеша

Пулы кеша определяют три метода поиска объектов кеша. Наиболее распространённым методом является getItem($key), который возвращает идентификатор объекта кеша по заданному ключу:

1
2
3
4
use Symfony\Component\Cache\Adapter\FilesystemAdapter;

$cache = new FilesystemAdapter('app.cache');
$latestNews = $cache->getItem('latest_news');

Если для заданного ключа не определено ни одного объекта, метод не возвращает значение null, а возвращает пустой объект, реализующий класс CacheItem.

Если вам нужно извлечь несколько объектов кеша одновременно, то лучше используйте метод getItems(array($key1, $key2, ...)):

1
2
// ...
$stocks = $cache->getItems(array('AAPL', 'FB', 'GOOGL', 'MSFT'));

Опять же, если ни один из ключей не представляет валидный объект кеша, вы не получите значение null,а получите пустой объект CacheItem.

Последний метод, связанный с извлечением объектов кеша, является hasItem($key), который возвращает true, если существует объект кеша, идентифицироанный заданным ключом:

1
2
// ...
$hasBadges = $cache->hasItem('user_'.$userId.'_badges');

Сохранение объектов кеша

Наиболее распространённым методом для сохранения объектов кеша является Psr\\Cache\\CacheItemPoolInterface::save, который сохраняет объект в кеше незамедлительно (возвращает true, если объект был сохранён, или false, если произошла какая-то ошибка):

1
2
3
4
// ...
$userFriends = $cache->getItem('user_'.$userId.'_friends');
$userFriends->set($user->getFriends());
$isSaved = $cache->save($userFriends);

Иногда вам может захотеться не сохранять объекты немедленно, чтобы повысить производительность вашего приложения. В таких случаях, используйте метод Psr\\Cache\\CacheItemPoolInterface::saveDeferred, чтобы отметить объекты кеша, как "готовые к сохранению" и потом вызовите метод Psr\\ache\\CacheItemPoolInterface::commit, когда вы будете готовы сохранить их все:

1
2
3
4
5
6
7
8
// ...
$isQueued = $cache->saveDeferred($userFriends);
// ...
$isQueued = $cache->saveDeferred($userPreferences);
// ...
$isQueued = $cache->saveDeferred($userRecentProducts);
// ...
$isSaved = $cache->commit();

Метод saveDeferred() возвращает true, когда объект кеша был успешно добавлен в "очередь сохранения", и false в других случаях. Метод commit() возвращает true, когда все ожидающие объекты были успешно сохранены, и false в других случаях.

Удаление объектов кеша

Пулы кеша включают методы для удаления объекта кеша, некоторых из них, или всех. Наиболее распространённым является Psr\\Cache\\CacheItemPoolInterface::deleteItem, который удаляет объект кеша, определяемый заданным ключом (возвращает true, когда объект был успешно удалён или не существует, и false в других случаях):

1
2
// ...
$isDeleted = $cache->deleteItem('user_'.$userId);

Используйте метод Psr\\Cache\\CacheItemPoolInterface::deleteItems, чтобы удалять несколько объектов кеша одновременно (возвращает true только, если все объекты были удалены, даже если один или несколько из них не существуют):

1
2
// ...
$areDeleted = $cache->deleteItems(array('category1', 'category2'));

Наконец, чтобы удалить все объекты кеша, хранящиеся в пуле, используйте метод Psr\\Cache\\CacheItemPoolInterface::clear (который возвращает true, когда все объекты были успешно удалены):

1
2
// ...
$cacheIsEmpty = $cache->clear();

Tip

Если компонент кеша используется внутри приложения Symfony, вы можете удалить объекты из пулов кеша, используя следующий команды (которые находятся в рамках пакета framework ):

Для того, чтобы удалить один конкретный объект из заданного пула:

1
2
3
4
$ php bin/console cache:pool:delete <cache-pool-name> <cache-key-name>

# deletes the "cache_key" item from the "cache.app" pool
$ php bin/console cache:pool:delete cache.app cache_key

Вы также можете удалить все объекты из заданного пула(ов):

1
2
3
4
5
6
7
$ php bin/console cache:pool:clear <cache-pool-name>

# очищает пул "cache.app"
$ php bin/console cache:pool:clear cache.app

# очищает пул "cache.validation" и "cache.app"
$ php bin/console cache:pool:clear cache.validation cache.app

4.1

Команда cache:pool:delete была представлена в Symfony 4.1.

Отсечение объектов кеша

Некоторые пулы кеша не включают в себя автоматизированный механизм для отсечения просроченных объектов кеша. Например, кеш FilesystemAdapter не удаляет просроченные объекты кеша пока объект не будет ясно запрошен и определён, как испорченный, например, через вызов к Psr\\Cache\\CacheItemPoolInterface::getItem. При определённой нагрузке, это может привести к сохранению устарелых записей кеша после срока истечения их действия, что, в свою очередь, приведёт к ощутимому потреблению зря потраченного пространства на диске или памяти в связи с излишними просроченными объектами кеша.

Этот недостаток был решён путём введения PruneableInterface, который определяет абстрактный метод prune(). ChainAdapter , FilesystemAdapter, PdoAdapter, и PhpFilesAdapter - все реализуют этот новый интерфейс, позволяя ручное удаление устаревших объектов кеша:

1
2
3
4
5
use Symfony\Component\Cache\Adapter\FilesystemAdapter;

$cache = new FilesystemAdapter('app.cache');
// ... провести какие-то операции set и get
$cache->prune();

Релизация ChainAdapter не содержит напрямую какой-либо логики усечения. Вместо этого, при вызове метода цепи адаптеров prune(), вызов делегируется всем совместимым с ним адаптерам кеша (а те, которые не реализуют PruneableInterface, тихо игнорируются):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
use Symfony\Component\Cache\Adapter\ApcuAdapter;
use Symfony\Component\Cache\Adapter\ChainAdapter;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Symfony\Component\Cache\Adapter\PdoAdapter;
use Symfony\Component\Cache\Adapter\PhpFilesAdapter;

$cache = new ChainAdapter(array(
    new ApcuAdapter(),       // does NOT implement PruneableInterface
    new FilesystemAdapter(), // DOES implement PruneableInterface
    new PdoAdapter(),        // DOES implement PruneableInterface
    new PhpFilesAdapter(),   // DOES implement PruneableInterface
    // ...
));

// prune will proxy the call to PdoAdapter, FilesystemAdapter and PhpFilesAdapter,
// while silently skipping ApcuAdapter
$cache->prune();

Tip

Если компонент кеша использовуется внутри приложения Symfony, то вы можете отсечь все объекты из всех пулов, используя следующую команду (которая находится в пакете framework ):

1
$ php bin/console cache:pool:prune