Table des matières :
- Cache objet Redis vs cache HTTP : arrêter de confondre les couches
- Anatomie du cache objet WordPress : groupes, clés, drop-in et incohérences charmantes
- Déployer Redis proprement : mémoire, politiques d’éviction, persistance et topologies HA
- Brancher WordPress sur Redis : plugin, extension PHP, multisite et WooCommerce
- Sécuriser Redis (vraiment) : ACL, TLS, réseau, et pourquoi
bind 0.0.0.0est un crime - Observabilité & tuning : hit ratio, latence P99, Core Web Vitals et coût cloud
Sur WordPress, « optimiser » veut souvent dire « ajouter un plugin de cache et prier ». Ça marche… jusqu’au jour où WooCommerce lance une promo, où le back‑office fait exploser wp_options, et où votre CPU découvre une passion soudaine pour les requêtes MySQL répétées. Le cache objet Redis, lui, vise une cible beaucoup plus prosaïque et rentable : éviter de recalculer en boucle des structures PHP déjà connues (options, résultats de requêtes, fragments de sessions applicatives, etc.).
Si vous avez déjà un cache HTTP (Varnish/NGINX/CDN), vous avez peut‑être l’illusion d’être « couverts ». Spoiler : non. Le cache HTTP accélère les pages cacheables côté front. Le cache objet Redis accélère tout ce qui se passe avant la génération HTML, y compris les requêtes admin, les endpoints AJAX, REST, le cron, et les pages non cacheables (panier, checkout, compte…). Et sur un WordPress moderne, c’est souvent là que se cache (haha) la facture.
Objectif de ce guide : implémenter un cache objet WordPress performant avec Redis, de façon propre (architecture, sécurité, HA, observabilité), et avec des critères mesurables (hit ratio, latence p99, TTFB, réduction des requêtes DB). Parce que « on a mis Redis » n’a jamais été un KPI.
Un point de cadre important (souvent sous‑estimé) : Redis est un accélérateur. Si votre site est lent à cause d’un thème trop lourd, d’images non optimisées, d’une surcharge JS ou d’un hébergement saturé, Redis ne « corrige » pas la cause. En revanche, il réduit la pression sur MySQL et sur PHP pour tout ce qui est répétitif, ce qui se voit immédiatement en stabilité sous charge (paniers, admin, endpoints dynamiques).
Cache objet Redis vs cache HTTP : arrêter de confondre les couches
Le cache HTTP (Varnish, NGINX FastCGI cache, CDN) agit au niveau des réponses HTTP : si l’URL + headers + cookies matchent, on ressert une réponse sans réveiller PHP. Très efficace pour du contenu public, et on en parle en détail dans Varnish Cache : optimiser le cache HTTP et réduire la charge serveur.
Le cache objet (Redis/Memcached) agit au niveau applicatif. WordPress met en cache des objets PHP sérialisés (résultats SQL, options, fragments calculés) via l’API wp_cache_*. Par défaut, c’est un cache en mémoire non persistant entre requêtes (sans drop‑in, il disparaît à la fin de chaque requête). Avec Redis, on rend ce cache persistant entre requêtes, ce qui réduit drastiquement les allers‑retours vers MySQL.
Pour éviter les discussions floues, voici une comparaison simple (à garder en tête quand vous priorisez vos optimisations) :
| Couche | Ce qui est mis en cache | Ce que ça accélère vraiment | Limites typiques |
|---|---|---|---|
| Cache HTTP (CDN/Varnish/NGINX) | HTML/JSON déjà rendu (réponse HTTP) | Pages publiques et endpoints cacheables | Pages personnalisées (cookies), panier/checkout, admin |
| Cache objet (Redis) | Résultats de requêtes, options, objets WP sérialisés | Génération serveur (PHP + MySQL), admin, cron, AJAX/REST | Invalidation, mémoire, données volatiles, cohérence applicative |
| Cache opcode (OPcache) | Bytecode PHP | Temps d’exécution PHP (compilation) | N’enlève pas les requêtes MySQL |
L’intérêt devient évident sur les parcours non cacheables côté HTTP (et donc, ceux qui font votre chiffre d’affaires). WooCommerce en est l’exemple canonique : panier/checkout, prix dynamiques, règles promo, stock, endpoints wc-ajax. Si vous préparez une infra pour des pics (Black Friday, campagnes TV, influence, etc.), Redis n’est pas « nice to have », c’est un amortisseur. Voir aussi : Préparer l’infrastructure aux pics (WooCommerce).
Mini‑scénario réaliste : pendant une promo, un visiteur ajoute 3 produits au panier. Même si la page “panier” n’est pas cacheable en HTTP, WordPress/WooCommerce va souvent relire plusieurs fois des options, des règles de taxe, des méthodes de livraison, des meta produits, etc. Sans cache objet persistant, vous payez à chaque hit un ensemble de requêtes répétitives. Avec Redis, une partie significative de ces lectures redevient “mémoire” plutôt que “SQL”.
Côté SEO/perf, l’amélioration se voit surtout sur TTFB et sur la stabilité sous charge. Et ça retombe ensuite sur les Core Web Vitals : Google rappelle que « Core Web Vitals are a set of real-world, user-centered metrics that quantify key aspects of the user experience » (web.dev/vitals). Pour le lien entre perf et SEO, vous pouvez croiser avec : Core Web Vitals et SEO.
Anatomie du cache objet WordPress : groupes, clés, drop-in et incohérences charmantes
WordPress expose une API de cache (wp_cache_get(), wp_cache_set(), etc.) implémentée par la classe WP_Object_Cache. Sans “drop‑in”, ce cache est juste un tableau PHP vivant pendant la requête. Dès que vous ajoutez un fichier wp-content/object-cache.php (un drop‑in), WordPress délègue le stockage à un backend persistant (Redis ici). C’est simple… et c’est précisément pour ça que tout le monde se plante : la simplicité masque les impacts sur cohérence, invalidation, et mémoire.
Référence utile (pour cadrer ce que WordPress attend d’un backend de cache) : la documentation développeur autour de WP_Object_Cache permet de comprendre la surface fonctionnelle minimale et les comportements attendus : WP_Object_Cache (dev).
Le cache est segmenté en groupes (groups) et en clés (keys). Certains groupes sont marqués comme non persistent (ex. objets trop volatiles) pour éviter de polluer Redis. D’autres sont global groups en multisite (partagés entre sites). Le design a une conséquence pratique : si votre plugin ou votre thème fait n’importe quoi (clés non préfixées, sérialisation d’objets massifs, absence de TTL), Redis ne « répare » rien. Il accélère aussi les mauvaises idées.
Quelques erreurs fréquentes (et coûteuses) qu’on voit en audit :
- Clés trop “grosses” : sérialiser une énorme structure (ex. une page builder entière, ou un tableau produit gigantesque) puis la stocker sans TTL. Résultat : RAM consommée, évictions, et performances instables.
- Absence de stratégie d’expiration : “si ça marche une fois, ça marche toujours”. Non : vous devez accepter qu’un cache se reconstruit, et donc définir une durée de vie compatible avec votre métier (prix, stock, contenu, règles).
- Cache d’objets sensibles : selon les extensions, des tokens, sessions, ou données personnelles peuvent se retrouver sérialisés. Ce n’est pas automatiquement un problème, mais ça devient un sujet de gouvernance (accès, dumps, rétention, incident).
- Incohérences entre couches : purger le cache HTTP sans purger certains fragments applicatifs (ou l’inverse) peut créer une sensation de “bug aléatoire”.
Et puis il y a le sujet qui fait sourire jaune : l’invalidation. La formule “cache invalidation” est souvent attribuée à Phil Karlton et largement reprise, mais l’important ici n’est pas la paternité : c’est le constat. WordPress invalide déjà des objets via hooks (clean_post_cache, updated_option, etc.). Mais certains plugins court‑circuitent les APIs, ou stockent des structures métiers sans stratégie de purge. Résultat : vous gagnez en vitesse… et vous perdez en justesse. Le cache, c’est un contrat. Faites‑le respecter.
Conseil pratico‑pratique : avant de déployer Redis, faites une photo de référence (baseline). Par exemple :
- nombre moyen de requêtes MySQL sur 20 pages clés (home, fiche produit, panier, checkout, admin),
- temps cumulé MySQL,
- TTFB sur ces mêmes parcours (et pas uniquement la home publique). Ensuite seulement, vous mesurez l’écart après activation du cache objet.
Déployer Redis proprement : mémoire, politiques d’éviction, persistance et topologies HA
Redis se décrit lui‑même ainsi : « Redis is an open source, in-memory data structure store, used as a database, cache, and message broker. » (redis.io). Pour WordPress, on l’utilise essentiellement comme cache : latence faible, forte concurrence, et données “recalculables”. Ça implique deux décisions techniques : dimensionner la mémoire et choisir une politique d’éviction.
Sur une instance cache, la config minimale sérieuse ressemble à : maxmemory, maxmemory-policy, et une surveillance de la fragmentation. En e‑commerce, allkeys-lfu est souvent plus pertinent que allkeys-lru (les objets “chauds” restent). Exemple :
maxmemory 4gb
maxmemory-policy allkeys-lfu
activedefrag yes
lazyfree-lazy-eviction yes
lazyfree-lazy-expire yes
La taille ? Vous ne “devinez” pas. Vous mesurez. Un ordre de grandeur réaliste : si votre wp_options et vos résultats de requêtes répétés représentent 200–800 Mo sérialisés, prévoyez de la marge (x2) pour éviter une éviction permanente (thrash) qui recrée de la charge MySQL… donc l’inverse du but.
Pour dimensionner sans boule de cristal, vous pouvez procéder en 3 temps :
- Observer
used_memory_peak,evicted_keys,keyspace_hits/missessur une journée “normale” et une période de pic. - Identifier si vous êtes en régime d’éviction (évictions > 0 de façon continue = cache trop petit ou objets trop volumineux/mal expirés).
- Ajuster (RAM, TTL, ou politiques) avant d’attaquer le sujet HA.
Persistance : pour un cache pur, beaucoup d’équipes choisissent de minimiser la persistance (voire de la désactiver) afin d’éviter des IO inutiles. Mais si votre Redis devient “semi‑critique” (par exemple si vous y stockez des sessions applicatives), la stratégie change : vous devez clarifier ce qui se passe lors d’un redémarrage. Le point important n’est pas “RDB vs AOF” dans l’absolu : c’est d’éviter l’ambiguïté côté produit (“si Redis redémarre, est‑ce que des utilisateurs perdent leur panier ?”).
Ensuite, la topologie :
- Instance unique : le plus simple, souvent suffisant pour un WordPress mono‑nœud.
- Sentinel : HA avec failover, idéal si Redis est critique et que vous n’avez pas besoin de sharding applicatif.
- Redis Cluster : sharding natif, utile si le dataset dépasse la RAM d’un nœud ou si vous voulez scaler horizontalement. Attention : certains clients PHP et plugins gèrent mieux Sentinel que Cluster.
Dans le cloud, la géographie compte : si votre WordPress est en région France (par exemple Paris) et votre Redis dans une autre région, vous payez en latence et parfois en coûts réseau. Pour un cache objet, la règle opérationnelle reste la même : Redis doit être au plus proche des PHP‑FPM (même VPC/VNet, idéalement même zone) pour éviter que l’accès cache devienne un goulot.
En Kubernetes, Redis “stateful” signifie aussi stockage persistant, anti‑affinité, et réseau maîtrisé. Si votre infra k8s est en transition (Ingress, Gateway API, etc.), gardez en tête que la perf et la stabilité réseau sont centrales : Ingress Kubernetes et migration.
Brancher WordPress sur Redis : plugin, extension PHP, multisite et WooCommerce
Côté WordPress, le chemin le plus standard (et maintenable) passe par le plugin Redis Object Cache : Redis Object Cache (WP.org). Il installe un drop‑in object-cache.php et expose des commandes WP‑CLI utiles (wp redis enable, wp redis status). Vous pouvez aussi utiliser d’autres implémentations, mais l’enjeu n’est pas « le plugin » : c’est la qualité du client Redis (latence, sérialisation, support TLS, cluster/sentinel).
Deux détails qui évitent des heures de debug :
- Prévoyez un “interrupteur” de secours (
WP_REDIS_DISABLEDselon les implémentations, ou désactivation du drop‑in) pour pouvoir revenir en arrière rapidement si un plugin se met à mal se comporter. - Testez le comportement en cas d’indisponibilité Redis : un cache objet doit idéalement fail open (le site fonctionne, juste plus lent), pas “site down”.
Pour le client, trois options existent généralement :
- PhpRedis (extension C) : la référence performance : phpredis (GitHub).
- Relay (extension C orientée cache, très performante, avec cache local optionnel) : relay.so.
- Predis (PHP pur) : pratique, mais moins performant sous charge. Acceptable en dev, rarement un bon deal en prod.
Ensuite, configuration wp-config.php typique (à adapter) :
define('WP_CACHE', true);
define('WP_REDIS_HOST', 'redis.internal');
define('WP_REDIS_PORT', 6379);
// define('WP_REDIS_PASSWORD', '...'); // évitez si vous avez ACL/tls, mais ne laissez pas ouvert.
define('WP_REDIS_DATABASE', 0);
define('WP_REDIS_PREFIX', 'wp_prod:');
define('WP_REDIS_TIMEOUT', 1);
define('WP_REDIS_READ_TIMEOUT', 1);
define('WP_REDIS_MAXTTL', 86400);
Ajustements souvent utiles en production (selon votre contexte) :
- Si Redis est local au serveur WordPress, un socket Unix peut réduire la latence et simplifier le firewall (quand l’implémentation le supporte).
- En environnement staging, forcez un préfixe distinct (
wp_staging:) pour éviter toute collision accidentelle (et éviter de “polluer” le dataset prod en cas de mauvaise config).
Sur un multisite, le préfixage et les groupes globaux deviennent non négociables : un mauvais préfixe = collisions = bugs “fantômes”. Sur WooCommerce, surveillez la taille et la fréquence des écritures (sessions, fragments, prix). Et surtout : Redis ne remplace pas un MySQL sain. Si votre base est en vrac, commencez par la remise à plat (index, autoload, tables) : Optimisation base MySQL (article).
Checklist de validation après activation (rapide, mais efficace) :
- vérifier que le drop‑in est bien chargé (
wp redis status), - comparer le nombre de requêtes DB sur une page type (avant/après),
- contrôler
keyspace_hitsetkeyspace_misses(les misses doivent exister, mais pas exploser en continu), - vérifier qu’admin + checkout n’ont pas de comportement “bizarre” (prix, stock, coupons),
- simuler une panne Redis (arrêt 30 secondes) et confirmer que le site reste fonctionnel.
Sécuriser Redis (vraiment) : ACL, TLS, réseau, et pourquoi bind 0.0.0.0 est un crime
Redis exposé sur Internet sans protection, c’est un classique du bingo sécurité (avec “admin/admin” et “bucket S3 public”). Pour un cache objet WordPress, la règle de base est simple : Redis doit être joignable uniquement par WordPress, sur un réseau privé, avec des contrôles d’accès. Si vous êtes sur VPS/VM, le durcissement système et firewall restent la fondation : Durcissement VPS/VM.
En pratique, mettez au minimum :
bind 127.0.0.1(si local) ou bind sur IP privée,protected-mode yes,- ACL (Redis 6+) plutôt que l’unique mot de passe global,
- TLS si trafic inter‑nœuds ou réseau partagé,
- désactivation/renommage de commandes dangereuses si votre modèle de menace l’exige (à manier avec prudence, et à documenter).
Exemple minimaliste d’ACL (à tester selon votre plugin/client, car certains ont besoin de commandes additionnelles) :
ACL SETUSER wpapp on >MOTDEPASSE ~wp_prod:* +@read +@write -CONFIG -FLUSHALL -FLUSHDB
ACL SETUSER default off
Dernier point : la sécurité, ce n’est pas que le réseau. C’est aussi le pipeline (secrets, déploiement, accès) et la réponse à incident. Un dump Redis peut contenir des identifiants, des fragments de sessions, des tokens applicatifs — selon ce que vos plugins y mettent. En contexte RGPD, ce n’est pas un détail : même si Redis est “juste un cache”, vous devez traiter l’accès, la rétention (au moins via TTL) et la surface d’exfiltration avec sérieux.
Si vous passez Redis derrière un proxy (HAProxy/stunnel) pour TLS ou segmentation, faites‑le proprement : HAProxy & TLS. Et si vous voulez éviter les surprises côté dépôts et secrets, un plan de sécurisation CI/CD aide à ne pas committer “juste pour tester” un mot de passe Redis dans un repo : Sécuriser CI/CD.
Observabilité & tuning : hit ratio, latence P99, Core Web Vitals et coût cloud
Un cache objet Redis “réussi” se prouve par des métriques. Les minimums syndicals :
- hit ratio (hits / (hits + misses)),
- latence Redis (p50/p95/p99),
- taux d’éviction (
evicted_keys), - mémoire utilisée et fragmentation (
mem_fragmentation_ratio), - impact côté PHP/MySQL : nombre de requêtes DB par requête web, temps cumulé MySQL.
Quelques repères opérationnels (à interpréter selon votre site) :
- un hit ratio “correct” en WordPress se construit dans le temps ; si vous voyez 20–30% de hits après activation, ce n’est pas forcément un échec, mais ça peut indiquer que vos clés expirent trop vite, que Redis est trop petit (évictions), ou que votre trafic est très “long tail” ;
- une hausse d’évictions accompagnée d’une hausse des misses est un signal classique de thrash (cache trop petit ou mauvaise politique).
Redis expose beaucoup via INFO, et l’écosystème de monitoring est mature. Branchez un Redis exporter et graphez dans Prometheus/Grafana : Monitoring Redis avec Prometheus & Grafana. Si vous voulez corréler “une lenteur front” avec “un spike Redis” et “une saturation MySQL”, les traces distribuées et l’unification logs/metrics/traces via OpenTelemetry deviennent vite addictives (dans le bon sens) : OpenTelemetry et observabilité.
Côté perf web, ne fantasmez pas : Redis ne va pas miraculeusement améliorer votre LCP si votre hero image fait 6 Mo. Par contre, il réduit la variabilité du TTFB et améliore la tenue sous charge, ce qui aide INP/UX indirectement (moins de timeouts, moins de “backend jitter”). Mesurez en RUM si possible : RUM vs monitoring synthétique.
Pour relier technique et business, construisez un tableau avant/après sur quelques parcours :
- TTFB p95 sur “fiche produit” et “panier”,
- taux d’erreur (5xx) pendant un pic,
- temps moyen MySQL et CPU PHP,
- coût infra (RAM Redis, réseau inter‑zone si managé). Sur la partie “c’est bien joli, mais combien ça coûte ?”, un cache trop gros, trop chaud, ou mal configuré, c’est aussi une dérive FinOps (RAM, IOPS, réseau inter‑AZ) : FinOps et coût cloud.
Enfin, un rappel opérationnel : un cache qui évince en permanence recrée de la charge DB et dégrade la perf. Un cache qui “ne purge jamais” risque la dérive mémoire et les incohérences. Un cache sans alerting, c’est juste une panne future avec une date surprise.
Alertes simples (qui évitent beaucoup de souffrance) :
evicted_keys > 0sur une fenêtre glissante (à adapter), surtout si corrélé avec des hausses de latence,used_memory/maxmemory > 0.85(seuil à ajuster selon votre tolérance au risque),- p99 latence Redis anormale (souvent signe de saturation, swap, ou incident réseau),
- augmentation continue des
missessur des endpoints critiques (panier/checkout/admin).
Et si vous avez besoin d’une feuille de route technique (audit, design HA, runbooks, tests de charge), c’est exactement le genre de sujet qui se travaille en atelier plutôt qu’en mode “on verra en prod” : Direction technique externalisée (Vikings).