Компонент Кеш

Дата обновления перевода 2021-12-26

Компонент Кеш

Компонент Кеш предоставляет функции, охватывающие задачи кеша от простых, до продвинутых. Он нативно реализует PSR-6 и Контракты кеширования для отличного взаимодействия. Он создан для производительности и устойчивости, поставляется с готовыми к использованию адаптеами для наиболее распространенных бэкендов кеширования. Он подключает инвалидацию, основанную на тегах, и защиту от наплыва кеша, путем блокировок и раннего срока истечения.

Tip

Компонент также содержит адаптеры для преобразования между кешами PSR-6, PSR-16 и Doctrine. см.e Адаптеры для взаимодействия между кешами PSR-6 и PSR-16 и Адаптер кеша Doctrine.

5.4

Поддержка кеша Doctrine устарела в Symfony 5.4, и будет удалена в Symfony 6.0.

Установка

1
$ composer require symfony/cache

Note

Если вы устанавливаете этот компонент вне приложения Symfony, вам нужно подключить файл vendor/autoload.php в вашем коде для включения механизма автозагрузки классов, предоставляемых Composer. Детальнее читайте в этой статье.

Контракты кеша против PSR-6

Данный компонент включает в себя два разных подхода к кешированию:

Кеширование PSR-6:
Базовая система кеширования, которая включает в себя "пулы" и "объекты" кеша.
Контракты кеширования :
Более простой, но при этом более мощный способ хранить значения кеша, основываясь на обратных вызовах повторных вычислений.

Tip

Рекомендуется использование Контрактов кеширования: они требуют меньше рутинного кода и предоставляют защиту от наплыва кеша по умолчанию.

Контракты кеширования

Все адаптеры поддерживают Контракты кеширования. Они содержат только два метода: get() и delete(). Метода set() нет, так как метод get() как получает, так и устанавливает значения кеша.

Первое, что вам нужно сделать, - инстанциировать адаптер кеша. В этом примере используется FilesystemAdapter:

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

$cache = new FilesystemAdapter();

Теперь вы можете извлекать и удалять кешированные данные, используя этот объект. Первый аргумент метода get() - это ключ, произвольная строка, которую вы ассоциируете с кешированным значением, чтобы вы могли извлечь его позже. Второй аргумент - PHP-вызываемое, которое выполняется, когда ключ не найден в коде, чтобы сгенерировать и вернуть значение:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
use Symfony\Contracts\Cache\ItemInterface;

// Вызываемое будет выполнено только в случае неудачи кеша.
$value = $cache->get('my_cache_key', function (ItemInterface $item) {
    $item->expiresAfter(3600);

    // ... выполнить какой-то HTTP-запрос или сложные вычисления
    $computedValue = 'foobar';

    return $computedValue;
});

echo $value; // 'foobar'

// ... и удалить ключ кеша
$cache->delete('my_cache_key');

Note

Используйте теги кеша, чтобы удалять более одного ключа за раз. Прочтите больше в Инвалидация кеша.

Предотвращение наплыва

Контракты кеша также имеют встроенное предотвращение наплыва. Оно удалит всплески CPU в моменты, когда кеш будет холодным. Если образец приложения использует 5 секунд, чтобы вычислить данные, которые были кешированы в течение часа, и к этим данным запрашивается доступ 10 раз в секунду, это означает, что у вас в основном будут попадания в кеш, и все хорошо. Но через час, мы получим 10 новых запросов к холодному кешу. Поэтому данные будут вычисляться снова. А еще через секунду произойдет то же самое. Поэтому данные будут вычисляться примерно 50 раз до того, как кеш снова разогреется. Вот тут-то вам и понадобится предотвращение наплыва.

Первое решение - использовать блокировку: разрешать только один PHP-процесс (на основании хостинга) вычислять конкретный ключ в текущий момент времени. Блокировка встроена по умолчанию, поэтому вам не нужно делать ничего, кроме как пользоваться преимуществами контрактов кеширования.

Второе решение также встроено при использовании контрактов кеширования: вместо того, чтобы ждать полное время ожидания до истечения срока значения, повторно вычислите его до истечения срока. Алгоритм Вероятностного раннего истечения срока рандомно имитирует неудачу кеша для одного пользователя, в то время как другие получают кешированное значение. Вы можете контролировать его поведение с помощью третьего необязательного параметра get(), который является плавающим значением под названием "beta".

По умолчанию, бета равна 1.0, а более высокие значения означают более раннее повторное вычисление. Установите ее как 0, чтобы отключить раннее повторное вычисление, и как INF, чтобы форсировать немедленное повторное вычисление:

1
2
3
4
5
6
7
8
9
use Symfony\Contracts\Cache\ItemInterface;

$beta = 1.0;
$value = $cache->get('my_cache_key', function (ItemInterface $item) {
    $item->expiresAfter(3600);
    $item->tag(['tag_0', 'tag_1']);

    return '...';
}, $beta);

Общее кеширование (PSR-6)

Чтобы использовать общие возможности кеширования PSR-6, вам понадобится выучить его ключевые концепты:

Объект
Одна единица информации, хранящаяся в виде пары ключ-значение, где ключ - уникальный идентификатор информации, а значение - его содержимое; см. статью Объекты кеша, чтобы узнать больше.
Пул
Логическое хранилище объектов кеша.Все операции кеша (сохранение объектов, поиск объектов и др.) выполняются через пул. Приложения могут определять столько пулов, сколько необходимо.
Адаптер
Реализует сам механизм кеширования, чтобы хранить информацию в файловой системе, DB и др. Компонент предоставляет несколько готовых к использованию адаптеров для распространённых бэк-эндов кеширования (Redis, APCu, Doctrine, PDO, и т.д.)

Базовое применение (PSR-6)

Эта часть компонента является реализацией PSR-6, что означает, что его базовый API совпадает с определённым в стандарте. До того, как кешировать информацию, создайте пул кеша, используя любые встроенные адаптеры. Например, чтобы создать кеш, основанный на файловой системе, инстанциируйте FilesystemAdapter:

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

$cache = new FilesystemAdapter();

Теперь вы можете создавать, извлекать, обновлять и удалять объекты, используя этот пул кеша:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// создайте новый объект, пытаясь получить его из кеша
$productsCount = $cache->getItem('stats.products_count');

// назначьте значение объекту и сохраните его
$numProducts->set(4711);
$cache->save($numProducts);

// извлеките объект кеша
$productsCount = $cache->getItem('stats.products_count');
if (!$productsCount->isHit()) {
    // ... объект не существует в кеше
}
// извлеките значение, хранимое объектом
$total = $productsCount->get();

// удалите объект кеша
$cache->deleteItem('stats.products_count');

Чтобы увидеть список всех поддерживаемых адаптеров, см. Пулы кешей и поддерживаемые адаптеры.

Маршалинг (сериализация) данных

Note

Маршалинг и сериализация являются схожими концептами. Сериализация - это процесс перевода состояния объекта в формат, который может быть сохранен (например, в файл). Маршалинг - это процесс перевода как состояния объекта, так и его базы исходного кода, в формат, который может быть сохранен или передан.

Демаршалинг объекта производит копию изначального объекта, возможно путем автоматической загрузки определений класса объекта.

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

DefaultMarshaller использует serialize() или igbinary_serialize() PHP, если установлено расширение Igbinary. Есть и другие маршалеры, которые зашифровывают или сжимают данные перед их сохранением:

1
2
3
4
5
6
use Symfony\Component\Cache\Adapter\RedisAdapter;
use Symfony\Component\Cache\DefaultMarshaller;
use Symfony\Component\Cache\DeflateMarshaller;

$marshaller = new DeflateMarshaller(new DefaultMarshaller());
$cache = new RedisAdapter(new \Redis(), 'namespace', 0, $marshaller);