Компонент Cache
Дата оновлення перекладу 2025-07-25
Компонент Cache
Компонент Cache надає функції, які охоплюють задачі кешу від простих, до просунутих. Він нативно реалізує PSR-6 та Контракти кешування для відмінної взаємодії. Він створений для продуктивності та стійкості, поставляється з готовими до використання адаптерами для найбільш розповсюджених бек-ендів кешування. Він підключає інвалідацію, засновану на тегах, та захист від напливу кешу, шляхом блокувань та раннього строку закінчення дії.
Tip
Компонент також містить адаптери для перетворення між кешами PSR-6 та PSR-16. Див. Адаптери для взаємодії між кешами PSR-6 і PSR-16.
Установка
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): string {
$item->expiresAfter(3600);
// ... виконати якийсь HTTP-запит або складні обчислення
$computedValue = 'foobar';
return $computedValue;
});
echo $value; // 'foobar'
// ... та видалити ключ кешу
$cache->delete('my_cache_key');
Note
Використовуйте теги кешу, щоб видаляти більше одного ключа за раз. Прочитайте більше в Інвалідація кешу.
Створення підпросторів імен
7.3
Підпростори імен кешу були представлені в Symfony 7.3.
Іноді вам буде потрібно створювати залежні від контексту варіації даних, які повинні бути
кешовані. Наприклад, дані, що використовуються для відображення сторінки панелі інструментів,
можуть бути важкими у генеруванні та унікальними для кожного користувача, тому ви не можете
кешувати однакові дані для всіх.
У таких випадках Symfony дозволяє створювати різні контексти кешу за допомогою просторів імен. Простір імен кешу — це довільний рядок, який ідентифікує набір пов'язаних елементів кешу. Усі адаптери кешу, що надаються компонентом, реалізують NamespacedPoolInterface, який надає метод withSubNamespace().
Цей метод дозволяє вам присвоювати простори імен кешованим елементам, ясно додаючи префікс до їхніх ключів:
1 2 3 4 5 6 7
$userCache = $cache->withSubNamespace(sprintf('user-%d', $user->getId()));
$userCache->get('dashboard_data', function (ItemInterface $item): string {
$item->expiresAfter(3600);
return '...';
});
У цьому прикладі обʼєкт кешу використовує ключ dashboard_data, але він буде внутрішньо
збережений під простором імен, що засновується на поточному ID користувача. Це обробляється
автоматично, тому вам не потрібно вручну додавати префікси на кшталт user-27.dashboard_data.
Немає правил або обмежень стосовно того, як визначати простори імен кешу. Ви можете робити їх настільки детальними або настільки узагальненими, наскільки це потрібно вашому додатку:
1 2 3 4 5 6 7 8
$localeCache = $cache->withSubNamespace($request->getLocale());
$flagCache = $cache->withSubNamespace(
$featureToggle->isEnabled('new_checkout') ? 'checkout-v2' : 'checkout-v1'
);
$channel = $request->attributes->get('_route')?->startsWith('api_') ? 'api' : 'web';
$channelCache = $cache->withSubNamespace($channel);
Tip
Ви можете комбінувати простори імент кешу з тегами кешу для більш просунутих потреб.
Не існує вбудованого способу інвалидації кешу за простором імен. Натомість рекомендованим підходом є зміна самого простору імен. З цієї причини розповсюджено включення статичного або динамічного версіонування даних у простір імен кешу:
1 2 3 4 5 6 7 8 9
// для простих додатків може бути достатньо просто збільшувати статичний номер версії
$userCache = $cache->withSubNamespace(sprintf('v1-user-%d', $user->getId()));
// інші додатки можуть використовувати динамічне версіонування, засноване на даті (наприклад, щомісячно)
$userCache = $cache->withSubNamespace(sprintf('%s-user-%d', date('Ym'), $user->getId()));
// або навіть інвалидувати кеш за умови зміни даних користувача
$checksum = hash('xxh128', $user->getUpdatedAt()->format(DATE_ATOM));
$userCache = $cache->withSubNamespace(sprintf('user-%d-%s', $user->getId(), $checksum));
Запобігання напливу
Контракти кешу також мають вбудоване запобігання напливу. Воно видалить сплески 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): string {
$item->expiresAfter(3600);
$item->tag(['tag_0', 'tag_1']);
return '...';
}, $beta);
Доступні адаптери кешу
Доступні наступні адаптери кешу:
- Адаптер кешу APCu
- Адаптер масиву кешу
- Адаптер ланцюжку кешу
- Адаптер кешу Couchbase
- Адаптер колекції кешу Couchbase
- Адаптер кеша Doctrine
- Адаптер кешу Doctrine DBAL
- Адаптер кешу Filesystem
- Адаптер кешу Memcached
- Адаптер кешу PDO
- Адаптер кеша PDO & Doctrine DBAL
- Адаптер кешу масиву PHP
- Адаптер кешу файлів PHP
- Адаптер кешу Proxy
- Адаптер кешу Redis
Загальне кешування (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 використовує PHP-функцію
serialize() за замовчуванням, але ви можете опціонально використовувати функціюigbinary_serialize() з розширення Igbinary:
1 2 3 4 5 6 7 8 9
use Symfony\Component\Cache\Adapter\RedisAdapter;
use Symfony\Component\Cache\Marshaller\DefaultMarshaller;
use Symfony\Component\Cache\Marshaller\DeflateMarshaller;
$marshaller = new DeflateMarshaller(new DefaultMarshaller());
// ви можете за бажанням використати розширення Igbinary, якщо воно у вас встановлене
// $marshaller = new DeflateMarshaller(new DefaultMarshaller(useIgbinarySerialize: true));
$cache = new RedisAdapter(new \Redis(), 'namespace', 0, $marshaller);
Існують інші маршалери, які можуть шифрувати або стискати дані перед зберіганням.
7.2
У версіях Symfony до 7.2 функція igbinary_serialize() використовувалася за
замовчуванням, коли було встановлено розширення Igbinary. Починаючи з
Symfony 7.2, вам потрібно ввімкнути підтримку Igbinary явно.
Просунуте використання
- Адаптер кешу APCu
- Адаптер масиву кешу
- Адаптер ланцюжку кешу
- Адаптер кешу Couchbase
- Адаптер колекції кешу Couchbase
- Адаптер кеша Doctrine
- Адаптер кешу Doctrine DBAL
- Адаптер кешу Filesystem
- Адаптер кешу Memcached
- Адаптер кешу PDO
- Адаптер кеша PDO & Doctrine DBAL
- Адаптер кешу масиву PHP
- Адаптер кешу файлів PHP
- Адаптер кешу Proxy
- Адаптер кешу Redis
- Інвалідація кешу
- Обʼєкти кешу
- Пули кешу та підтримувані адаптери
- Адаптер кеша PDO & Doctrine DBAL
- Адаптер кеша Php массива
- Адаптер кеша прокси
- Адаптери для взаємодії між кешами PSR-6 і PSR-16