J'ai testé pour vous : le composant Cache de Symfony couplé à Redis


Principe du cache

exemples
- RAM
- Cache CPU
- Redis devant BDD
- DNS
- CDN
questions associées
- Espace de stockage limité ?
- Invalidation ?
cas simple
- Récupérer une donnée non cachée
- Invalider la donnée quand une màj est faite dans la source d'origine

Besoin classique
- Nombreux accès à une BDD, requêtes complexes
- Redis : clé-valeur
- Pratique pour stocker des choses simplement
key_1: 'value_1'
key_2: 2
key_3: '{firstName: Ando, lastName: Larz}'symfony cache
- Symfony 3.3
- PSR 16 Simple cache
- PSR 6 Cache
- Nombreux adapters (Filesystem, Redis, Memcached, PDO, chain, etc)
notre cas d'usage
- Site de voyages, produits complexes
- Données maîtrisées dans un système externe
- Plusieurs pools, dont un pour les produits
notre cas d'usage
# config/packages/cache.yaml
framework:
cache:
default_redis_provider: 'redis://%env(REDIS_CACHE_HOST)%:%env(REDIS_CACHE_PORT)%'
pools:
# Individual pools for different product cache usages
product.cache_pool:
adapter: 'cache.adapter.redis_tag_aware'
tags: true
default_lifetime: 28800
# Other pools ...notre cas d'usage
$this->productCachePool->get(
$productCacheKey,
function (ItemInterface $item) use ($productId): CacheableProductDto {
$product = $this->productRepository->find($productId);
if (null === $product) {
throw new NotFoundHttpException();
}
$item->tag('product_tag');
$item->expiresAfter('3600');
return $cacheableProductDto;
}
);cas avancé
Administration du cache par les admins
- Afficher l'ensemble des clés
- Afficher un item
- Recherche par filtre
- Suppression d'une clé
- Suppression par filtre
- Suppression par tag
- Suppression totale
pools Symfony cache
- 'cache.taggable'
- Pas de `getAll()`
- Clés au format `xxx:my_key_1234`
- Tags spécifiques préfixés `\x01` (binaire)
Impliquent des manipulations spécifiques
Cas faciles
- Afficher un item
- Supprimer par tag
- Suppression totale
affichage de l'ensemble
- Rappel : plusieurs pools
- AutowireIterator sur `cache.taggable`
affichage de l'ensemble
trait CacheKeysTrait
{
private readonly \Redis $redisCache;
/**
* @return array<int, string>
*/
private function scanKeys(string $searchPattern): array
{
$cursor = null;
$keys = [];
do {
$retrievedKeys = $this->redisCache->scan($cursor, $searchPattern);
if (false !== $retrievedKeys) {
foreach ($retrievedKeys as $key) {
$keys[] = $key;
}
}
} while (0 !== $cursor);
return $keys;
}
}affichage de l'ensemble
- 'Sanitize' les clés
jamld6hgt:product_desert_marocain
affichage de l'ensemble
Filtrer les clés qui sont des tags
return b($poolCompatibleKey)->startsWith("\x01");affichage de l'ensemble
foreach ($this->cachePools as $cachePool) {
if (true === $cachePool->hasItem($poolCompatibleKey)) {
return $cachePool->getItem($poolCompatibleKey);
}
}Recherche par filtre
Même fonctionnement
- Scan Redis (avec pattern de filtrage)
- Sanitize
- Filtrage tags
- foreach
- Pagination
- Return
performances
TODO
suppression par filtre
- Scan Redis
- Sanitize des clés
- Filtrage des tags
suppression par filtre
foreach ($this->cachePools as $cachePool) {
if (true === $cachePool->hasItem($poolCompatibleKey)) {
$deletionSuccess = $cachePool->deleteItem($poolCompatibleKey);
if (false === $deletionSuccess) {
$failedDeletions[] = $key;
}
break;
}
}suppression par clé
if (false === $this->redisCache->get($cacheKey)) {
$this->logger->warning('Tried to delete {cacheKey} cache key, but it was not found.', [
'cacheKey' => $cacheKey,
]);
return;
}conclusion
Idéal pour stocker et récupérer des items en cache
Pour les besoins plus avancés :
- Compléter en accédant directement au cache
- Comprendre la gestion des pools et tags
merci !
QR Code pour les retours
Minimal
By Andoni Larzabal
Minimal
- 0