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

Дата оновлення перекладу 2022-04-28

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

Компонент Кеш надає функції, які охоплюють задачі кеша від простих, до просунутих. Він нативно реалізує PSR-6 та Контракти кешування для відмінної взаємодії. Він створений для продуктивності та стійкості, поставляється з готовими до використання адаптерами для найбільш розповсюджених бек-ендів кешування. Він підключає інвалідацію, засновану на тегах, та захист від напливу кешу, шляхом блокувань та раннього строку закінчення дії.

Tip

Компонент також містить адаптери для перетворення між кешами PSR-6, PSR-16 та Doctrine. Див. Адаптери для взаємодії між кешами 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, вам знадобиться вивчити його ключові концепти:

Об'єкт
Одна одиниця інформації, яка зберігається у вигляді пари ключ-значення, де ключ - унікальний ідентифікатор інформації, а значення - його зміст; див. статтю Обʼєкты кеша, щоб дізнаится більше.
Пул
Логічне сховище об'єктів кешу. Всі операції кешу (зберігання об'єктів, пошук об'єктів та ін.) виконуються через пул. Додатки можуть визначати стільки пулів, скіль необхідно.
Адаптер
Реадізує сам механізм кешування, щоб зберігати інформацію в файловій системі, базі даних та ін. Компонент надає декілька готових до використання адаптерів для розповсюджених бек-ендів кешування (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);