Symfony & Doctrine Cache L2 : Pourquoi Redis est le choix ultime pour un cache ultra-performant ?

la mise en cache avec Redis et Symfony 7

Introduction : Boostez votre Cache avec Redis et Doctrine L2

Comme nous l’avons vu précédemment, le cache est un élément clé pour optimiser la performance d’une application Symfony. Par défaut, Symfony propose le FileSystem Cache, qui stocke les données en local sur le disque. C’est une solution viable pour des besoins basiques, mais lorsqu’on cherche une performance pure, le cache en mémoire est la meilleure option.

C’est là que Redis entre en jeu. 🔥

✅ Pourquoi Redis ?
Redis est un cache en mémoire ultra-rapide, conçu pour gérer des volumes de données importants avec des temps de réponse extrêmement faibles. Il est idéal pour un cache L2 dans Doctrine, permettant d’accélérer les requêtes SQL en réduisant les accès à la base de données.

🎯 Dans cet article, nous allons voir :

  • Pourquoi Redis est le choix idéal pour Symfony & Doctrine.
  • Comment mettre en place un cache L2 performant.
  • Comment visualiser et manipuler les données stockées dans Redis avec RedisCommander.

Préparez-vous à donner un coup de boost à vos query !

Installation et mise en place de Redis pour Symfony & Doctrine

Afin d’éviter une configuration trop complexe, j’ai choisi d’installer l’extension Redis pour PHP via PECL, plutôt que de tout Dockeriser. Cette méthode est rapide et efficace pour un environnement de développement ou même en production avec un serveur Redis distant.

1. Installation de l’extension Redis pour PHP

Avant toute chose, il faut installer l’extension Redis pour PHP :

pecl install redis

Si vous utiliser Mac OS et Homebrew l’extension sera activé automatiquement.

2. Ajout de Redis et Redis Commander dans Docker Compose

Pour gérer Redis facilement sans installation locale, j’ai ajouté Redis et Redis Commander dans mon fichier docker-compose.yml.

version: '3.8'

services:
  redis:
    image: redis:alpine
    command: redis-server --appendonly yes
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data
    networks:
      - app-network
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis-commander:
    image: ghcr.io/joeferner/redis-commander:latest
    environment:
      - REDIS_HOSTS=local:redis:6379
    ports:
      - "8081:8081"
    networks:
      - app-network
    platform: linux/arm64
    depends_on:
      - redis

networks:
  app-network:

volumes:
  redis_data:

3. Pourquoi une interface pour Redis ?

Utiliser Redis en ligne de commande, c’est bien, mais avoir une interface graphique, c’est encore mieux ! C’est pourquoi j’utilise Redis Commander, qui permet de :

✅ Visualiser les clés stockées en cache.
✅ Voir la structure et la valeur des données.
✅ Éditer et supprimer des entrées facilement.
✅ Surveiller l’évolution du cache en temps réel.

Avec Docker, Redis Commander devient un outil incontournable pour analyser l’impact du cache et affiner sa configuration.

visualisation des données mis en cache Redis via Doctrine Symfony

⚠️ Attention : Bien configurer l’attribut de l’entité pour le Warm-Up !

Par défaut, Doctrine ne met pas automatiquement toutes les entités en cache. Il faut s’assurer que l’entité est bien configurée pour que le Cache L2 fonctionne correctement.

Gestion du Warm-Up avec NONSTRICT_READ_WRITE dans Doctrine Cache L2

#[ORM\Cache(usage: 'NONSTRICT_READ_WRITE', region: 'product_region')]

Tu actives une mise en cache avancée, qui permet un warm-up automatique dès qu’un administrateur met à jour un produit. Cela signifie que :

✅ La mise en cache est intelligente : les nouvelles données sont enregistrées sans invalider tout le cache.
✅ Doctrine met à jour les entrées dès la requête suivante, ce qui optimise les performances sans bloquer l’accès aux données.

Comment fonctionne NONSTRICT_READ_WRITE ?

Contrairement à READ_ONLY, qui est strict et ne met en cache que des données statiques, NONSTRICT_READ_WRITEassure une mise à jour progressive du cache lorsque l’application effectue des modifications.

📌 Cas d’usage concret :

  • Un admin modifie un produit via le back-office.
  • La modification est enregistrée en base et Doctrine invalide seulement l’entrée concernée dans Redis.
  • Lors de la prochaine requête, si l’élément n’est pas en cache, il est rechargé en base et stocké à nouveau dans Redis automatiquement.
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
#[ORM\Cache(usage: 'NONSTRICT_READ_WRITE', region: 'product_region')]
class Product
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private int $id;

    #[ORM\Column(length: 255)]
    private string $name;

    #[ORM\Column]
    private ?float $price = null;

    #[ORM\Column(type: 'text', nullable: true)]
    private ?string $description = null;

    // Getters & Setters...
}

Avantages de cette configuration :

✅ Moins de requêtes SQL : Doctrine utilise Redis comme un buffer pour les objets fréquemment accédés.
✅ Mise à jour contrôlée du cache : Seuls les objets modifiés sont invalidés et rechargés.
✅ Performances optimisées : Parfait pour un catalogue produit dynamique sans ralentir la base de données.

Mise en place avec Symfony

Contrairement à une configuration via le Filesystem, il est possible d’utiliser directement Redis grâce à cache.adapter.redis. Cette méthode nécessite l’installation d’un package via Composer, mais offre un gros avantage : toute la configuration est automatiquement gérée par Symfony.

Ajoutez cette configuration dans cache.yaml

framework:
    cache:
        app: cache.adapter.redis
        default_redis_provider: '%env(REDIS_URL)%'
        pools:
            doctrine.second_level_cache_pool:
                adapter: cache.adapter.redis
  
Explications :
  • app: cache.adapter.redis → Définit Redis comme cache principal pour Symfony.
  • default_redis_provider: '%env(REDIS_URL)%' → Utilise l’URL Redis spécifiée dans les variables d’environnement.
  • doctrine.second_level_cache_pool → Pool de cache dédié pour Doctrine L2

3. Configuration du cache L2 dans Doctrine

 Ajoutez cette configuration dans config/packages/doctrine.yaml

doctrine:
    orm:
        second_level_cache:
            enabled: true
            region_cache_driver:
                type: pool
                pool: doctrine.second_level_cache_pool

            # Déclaration des régions
            regions:
                product_region:
                    cache_driver:
                        type: pool
                        pool: doctrine.second_level_cache_pool
                    lifetime: 3600  # Durée de vie en secondes (optionnel)

Explications :

  • enabled: true → Active le cache L2 pour Doctrine.
  • region_cache_driver → Définit Redis comme moteur de cache.
  • product_region → Région spécifique pour l’entité Product, avec une durée de vie de 3600s.

4. Explication du fonctionnement

Grâce à l’annotation #[ORM\Cache(usage: 'NONSTRICT_READ_WRITE', region: 'product_region')], le cache se met automatiquement à jour dès qu’un produit est modifié par un administrateur.

Pourquoi c’est intéressant ?
✅ Doctrine stocke les résultats de requêtes SQL directement en cache.
✅ Lorsqu’un admin met à jour un produit, la région product_region est automatiquement mise à jour.
✅ Cela évite de recharger la base de données inutilement et booste la performance de l’application.

FileSystem vs Redis

Quand on parle de mise en cache dans Symfony, la première option par défaut est souvent le FileSystem. C’est simple, efficace pour des petits projets, mais lorsqu’on cherche à maximiser la performance, Redis est le choix ultime.

Performance : Redis écrase FileSystem

D’après mes tests personnels, voici une comparaison entre les deux solutions :

Méthode de cacheTemps moyen par requête
FileSystem⏳ ~40ms
Redis⚡ ~20ms (2x plus rapide !)

Redis est donc 2x plus rapide que FileSystem ! 🎯

Pourquoi une telle différence ?

  • FileSystem doit lire et écrire sur le disque, ce qui prend du temps.
  • Redis, lui, stocke les données en mémoire et y accède quasi instantanément.

Consommation mémoire : Redis libère PHP

Un autre avantage de Redis, c’est qu’il libère de la mémoire PHP.

Avec FileSystem, PHP doit gérer :
❌ L’accès aux fichiers (IO Disk)
❌ Le chargement des données en mémoire
❌ Leur désérialisation

Avec Redis, c’est Redis lui-même qui gère ces tâches, ce qui signifie :
✅ Moins de charge pour PHP
✅ Plus de mémoire libre pour exécuter l’application
✅ Une meilleure réactivité globale

Et comme PHP n’a pas que le cache à gérer, toute cette mémoire économisée peut être utilisée pour les vraies opérations métier de l’application.


Conclusion : Redis, l’Optimisation Ultime pour Symfony & Doctrine

Il est vrai que Redis peut sembler légèrement plus complexe à mettre en place qu’un simple FileSystem. Mais grâce à Docker, son intégration devient rapide et efficace, évitant les installations manuelles fastidieuses.

Et une fois la configuration bien en placetout fonctionne instantanément ! Si vous aviez déjà un cache FileSystem opérationnel, la migration vers Redis est fluide et transparente.


Nous avons vu que Redis divise par deux le temps d’accès au cache, comparé à FileSystem. Et ce n’est pas tout :

📌 Sans cache → Temps standard
📌 Avec FileSystem → 2x plus rapide
📌 Avec Redis → Encore 2x plus rapide que FileSystem !

👉 Résultat : une application Symfony jusqu’à 4x plus rapide tout en maintenant la cohérence des données !

Grâce à Redis, Symfony devient plus performant, plus réactif et consomme moins de ressources. C’est une arme incontournable pour tout projet à forte charge.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *