Кеш
Дата оновлення перекладу 2022-12-11
Кеш
Використання кешу - чудовий спосіб прискорити ваш додаток. Компонент Symfony Cache постчається з багатьма адаптерами для різних сховищ. Кожний адаптер розроблено для високої ефективності.
Наступний приклад демонструє типове використання кешу:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
use Symfony\Contracts\Cache\ItemInterface;
// Викличне буде запущено лише за відсутності значення в кеші
$value = $pool->get('my_cache_key', function (ItemInterface $item) {
$item->expiresAfter(3600);
// ... зробити HTTP-запит або складні обчислення
$computedValue = 'foobar';
return $computedValue;
});
echo $value; // 'foobar'
// ... та видалити ключ кешу
$pool->delete('my_cache_key');
Symfony підтримує Cache Contracts, PSR-6/16 та інтерфейси Doctrine Cache. Ви можете прочитати більше про них у документації компонента.
Налаштування кешу з FrameworkBundle
Коли ви налаштовуєте компонент Cache, є декілька концепцій, про які варто знати:
- Пул
- Це сервіс з яким ви будете взаємодіяти. Кожний пул завжди буде мати свій простір імен і кешовані елементи. Н буває конфліктів між різними пулами.
- Адаптер
- Адаптер - це шаблон, який ви використовуєте для створення пулу.
- Провайдер
- Провайдер - це сервіс, який адаптери використовують для підключення до сховища. Прикладами таких адаптерів є Redis та Memcached. Якщо в якості провайдеру використовується DSN, то автоматично створється сервіс.
Є 2 пули, включені за замовчуванням. Це cache.app
та cache.system
. Системний кеш
використовується для речей на кшталт анотацій, серіалізатора та валідації. cache.app
може використовуватися у вашому коді. Ви можете налаштувати, який адаптер (шаблон) вони
будуть використовувати, використавши ключі app
та system
як:
- YAML
- XML
- PHP
1 2 3 4 5
# config/packages/cache.yaml
framework:
cache:
app: cache.adapter.filesystem
system: cache.adapter.system
Tip
Хоча переконфігурувати кеш system
можливо, рекомендовано
залишити кофігурацію за замовчуванням, застосовану Symfony.
Компонент Cache постачається з набором сконфігурованих адаптерів:
- cache.adapter.apcu
- cache.adapter.array
- cache.adapter.filesystem
- cache.adapter.memcached
- cache.adapter.pdo
- cache.adapter.psr6
- cache.adapter.redis
- cache.adapter.redis_tag_aware (адаптер Redis оптимізовано для роботи з тегами)
Деякі з цих адаптерів можуть бути налаштовані з допомогою скорочень. При використанні цих
скорочень, будуть створені пули з id сервісів виду cache.[type]
.
- YAML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
# config/packages/cache.yaml
framework:
cache:
directory: '%kernel.cache_dir%/pools' # Використовується лише з cache.adapter.filesystem
# сервіс: cache.doctrine
default_doctrine_provider: 'app.doctrine_cache'
# сервіс: cache.psr6
default_psr6_provider: 'app.my_psr6_service'
# сервіс: cache.redis
default_redis_provider: 'redis://localhost'
# сервіс: cache.memcached
default_memcached_provider: 'memcached://localhost'
# сервіс: cache.pdo
default_pdo_provider: 'doctrine.dbal.default_connection'
- YAML
- XML
- PHP
1 2 3 4 5 6 7 8 9 10 11 12 13
# config/packages/cache.yaml
framework:
cache:
directory: '%kernel.cache_dir%/pools' # Only used with cache.adapter.filesystem
# сервіс: cache.psr6
default_psr6_provider: 'app.my_psr6_service'
# сервіс: cache.redis
default_redis_provider: 'redis://localhost'
# сервіс: cache.memcached
default_memcached_provider: 'memcached://localhost'
# сервіс: cache.pdo
default_pdo_provider: 'doctrine.dbal.default_connection'
Створення користувацьких пулів (з простором імен)
Ви також можете створити пули з іншими налаштуваннями:
- YAML
- XML
- PHP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
# config/packages/cache.yaml
framework:
cache:
default_memcached_provider: 'memcached://localhost'
pools:
# створить сервіс "custom_thing.cache"
# що автоматично підключається через "CacheInterface $customThingCache"
# використовує конфігурацію кеша "app"
custom_thing.cache:
adapter: cache.app
# створить сервіс "my_cache_pool"
# що автоматично підключається через "CacheInterface $myCachePool"
my_cache_pool:
adapter: cache.adapter.filesystem
# використовує налаштування вище default_memcached_provider
acme.cache:
adapter: cache.adapter.memcached
# керування налаштуваннями адаптера
foobar.cache:
adapter: cache.adapter.memcached
provider: 'memcached://user:password@example.com'
# використовує пул "foobar.cache" як бекенд, але налаштовує час життя
# і, як інші пули вище, має власний простір імен елементів кешу
short_cache:
adapter: foobar.cache
default_lifetime: 60
Кожний пул керує набором незалежних ключів кешу: ключі з різних пулів ніколи не перетинаються, навіть, якщо вони використовують один і той самий бекенд. Це досягається шляхом додавання префіксів до ключів з простором імен, який генерується хешуванням назви пуллу, імені скомпільованого калсу контейнера та налаштовуваним seed, яке за замовчуванням дорівнює каталогу проекту.
Кожний користувацький пул стає сервісом, чий id є імʼям пулу (наприклад, custom_thing.cache
).
Псевдонім для автопідключення також створюється для кожного пулу, використовуючи версію його
імені camel case - наприклад, custom_thing.cache
може автоматично впроваджуватися при назві
аргументу $customThingCache
з типом CacheInterface або
Psr\Cache\CacheItemPoolInterface
:
1 2 3 4 5 6 7 8 9 10 11 12 13
use Symfony\Contracts\Cache\CacheInterface;
// з методу контролера
public function listProducts(CacheInterface $customThingCache)
{
// ...
}
// в сервісі
public function __construct(CacheInterface $customThingCache)
{
// ...
}
Tip
Якщо вам потрібно, щоб простір імен був інтероперабельним зі стороннім додатком, то
ви можете контролювати автоматичне генерування, встановивши атрибут namespace
сервісного тегу cache.pool
. Наприклад, ви можете перевизначити сервісне визначення
адаптера:
- YAML
- XML
- PHP
1 2 3 4 5 6 7 8
# config/services.yaml
services:
# ...
app.cache.adapter.redis:
parent: 'cache.adapter.redis'
tags:
- { name: 'cache.pool', namespace: 'my_custom_namespace' }
Користувацькі налаштування провайдерів
Деякі провайдери мають специфічні налаштування конфігурації.
RedisAdapter дозволяє вам
створювати провайдерів з налаштуваннями timeout
, retry_interval
і так далі. Для
використання цих налаштувань зі значеннями не за замовчуванням, потрібео створити власний
провайдер \Redis
та використовувати його при конфігурації пулу.
- YAML
- XML
- PHP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
# config/packages/cache.yaml
framework:
cache:
pools:
cache.my_redis:
adapter: cache.adapter.redis
provider: app.my_custom_redis_provider
services:
app.my_custom_redis_provider:
class: \Redis
factory: ['Symfony\Component\Cache\Adapter\RedisAdapter', 'createConnection']
arguments:
- 'redis://localhost'
- { retry_interval: 2, timeout: 10 }
Створення ланцюжку кешів
Різні адаптери кешів мають свої сильні та слабкі сторони. Деякі можуть бути дуже швидкими, але оптимізованими для зберігання невеликих елементів, а деякі можуть зберігати багато даних, але достатньо повільні. Для отримання кращого від кожного, ви можете використовувати ланцюжок адаптерів.
Ланцюжок кешів обʼєднує декілька пулів кешів в один. При збереженні елемента у ланцюжок кешів, Symfony зберігає його послідовно в усі пули. При отриманні елемента Symfony намагається отримати його з першого пулу. Якщо його не знайдено, пробує наступні пули, поки не знайде елемент або не зʼявиться виключення. Через таку поведінку, рекомендується визначати адаптери у ланцюжку починаючи з найшвидшого і закінчуючи найповільнішим.
Якщо трапляється помилка при збереженні елмента в пул, Symfony зберігає його в
інших пулах і не викликає виключення. Пізніше, при отриманні елемента, Symfony
автоматично зберігає елемент у всіх пулах, яких не вистачає.
- YAML
- XML
- PHP
1 2 3 4 5 6 7 8 9 10
# config/packages/cache.yaml
framework:
cache:
pools:
my_cache_pool:
default_lifetime: 31536000 # One year
adapters:
- cache.adapter.array
- cache.adapter.apcu
- {name: cache.adapter.redis, provider: 'redis://user:password@example.com'}
Використання тегів кешу
У додатках з великоою кількістю елементів може бути корисно організовувати збережені дані, щоб ефективніше інвалідувати кеш. Один з варіантів - використовувати теги кешу. До елемента кешу можна додати один або декілька тегів. Всі елементи з однаковим тегом можуть бути інвалідовані за допомогою виклику однієї функції:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
use Symfony\Contracts\Cache\ItemInterface;
use Symfony\Contracts\Cache\TagAwareCacheInterface;
class SomeClass
{
private $myCachePool;
// використовуємо автопідключення для впровадження пулу кешу
public function __construct(TagAwareCacheInterface $myCachePool)
{
$this->myCachePool = $myCachePool;
}
public function someMethod()
{
$value0 = $this->myCachePool->get('item_0', function (ItemInterface $item) {
$item->tag(['foo', 'bar']);
return 'debug';
});
$value1 = $this->myCachePool->get('item_1', function (ItemInterface $item) {
$item->tag('foo');
return 'debug';
});
// Видалити всі елементи ключа з тегом "bar"
$this->myCachePool->invalidateTags(['bar']);
}
}
Щоб ця функція працювала, потрібно щоб адаптер кешу реалізовував інтерфейс TagAwareCacheInterface. Тоді можна викристовувати наступне налаштування.
- YAML
- XML
- PHP
1 2 3 4 5 6 7
# config/packages/cache.yaml
framework:
cache:
pools:
my_cache_pool:
adapter: cache.adapter.redis
tags: true
Теги зберігаються в одному пулі за замовчуванням. Це добре у більшості випадків. Але інколи може бути краще зберігати теги в іншому пулі. Цього можна досягти за допомогою вказання адаптера.
- YAML
- XML
- PHP
1 2 3 4 5 6 7 8 9
# config/packages/cache.yaml
framework:
cache:
pools:
my_cache_pool:
adapter: cache.adapter.redis
tags: tag_pool
tag_pool:
adapter: cache.adapter.apcu
Note
Інтерфейс TagAwareCacheInterface
при автопідключенні використовує сервіс cache.app
.
Очищення кешу
Для очищенна кешу можна використовувати команду bin/console cache:pool:clear [pool]
.
Це видалить всі записи з вашого сховища і потрібно буде переобчислити всі значення.
Ви також можете згрупувати ваші пули в "очисники кешу". За замовчуванням, є 3 очисники
кеша:
cache.global_clearer
cache.system_clearer
cache.app_clearer
Глобальний очисник видалить всі елементи кешу в кожному пулі. Системний очисник кешу
використовується при команді bin/console cache:clear
. App clearer - це очисник за
замовчуванням.
Для перегляду всіх доступних пулів кешу:
1
$ php bin/console cache:pool:list
Очистити один пул:
1
$ php bin/console cache:pool:clear my_cache_pool
Очистити всі користувацькі пули:
1
$ php bin/console cache:pool:clear cache.app_clearer
Очистити всі кеші всюду:
1
$ php bin/console cache:pool:clear cache.global_clearer
Очистити кеш за тегом(ами):
6.1
Команда cache:pool:invalidate-tags
була представлена в Symfony 6.1.
1 2 3 4 5 6 7 8 9 10 11
# інвалідувати tag1 в усіх тегованих пулів
$ php bin/console cache:pool:invalidate-tags tag1
# інвалідувати tag1 і tag2 в усіх тегованих пулів
$ php bin/console cache:pool:invalidate-tags tag1 tag2
# інвалідувати tag1 і tag2 в пулі cache.app
$ php bin/console cache:pool:invalidate-tags tag1 tag2 --pool=cache.app
# інвалідувати tag1 і tag2 в пулах cache1 і cache2
$ php bin/console cache:pool:invalidate-tags tag1 tag2 -p cache1 -p cache2
Шифрування кешу
Для того, щоб зашифрувати кеш, використовуючи libsodium
, ви можете використати
SodiumMarshaller.
Для почтаку, вам необхідно згенерувати безпечний ключ та додати його в своє
сховище секретів у вигляді CACHE_DECRYPTION_KEY
:
1
$ php -r 'echo base64_encode(sodium_crypto_box_keypair());'
Потім, зареєструйте сервіс SodiumMarshaller
, використовуючи цей ключ:
- YAML
- XML
- PHP
1 2 3 4 5 6 7 8 9 10 11
# config/packages/cache.yaml
# ...
services:
Symfony\Component\Cache\Marshaller\SodiumMarshaller:
decorates: cache.default_marshaller
arguments:
- ['%env(base64:CACHE_DECRYPTION_KEY)%']
# використовуйте декілька ключів, щоб міняти їх
#- ['%env(base64:CACHE_DECRYPTION_KEY)%', '%env(base64:OLD_CACHE_DECRYPTION_KEY)%']
- '@Symfony\Component\Cache\Marshaller\SodiumMarshaller.inner'
Caution
Це зашифрує значення обʼєктів кешу, але не ключі кешу. Будьте обережні, щоб не припускати витіку конфіденційних даних у ключах кешу.
При конфігурації декількох ключів, перший ключ буде використовуватися для читання
та запису, а додатковий(і) ключ(і) будуть використовуватися лише для читання. Коли
всі обʼєкти кешу будуть зашифровані, а у старого ключа скінчиться строк дії, ви
можете повністю видалити OLD_CACHE_DECRYPTION_KEY
.