# OPTIM-03 — Redis Object Cache

**Date** : 2026-06-24
**Serveur** : 51.158.96.239 — Redis 7.0.15 (déjà actif), WordPress, PHP-FPM 8.3
**But** : soulager MariaDB en cachant les objets/requêtes WP en RAM (Redis), via le plugin gratuit
**Redis Object Cache** (Till Krüss).

## État avant
- Redis : actif, `bind 127.0.0.1 -::1` (localhost only, sûr), pas de password, `maxmemory=0`,
  `maxmemory-policy=noeviction`, DBSIZE 0 (inutilisé).
- `php8.3-redis` : **absent**.
- `DISALLOW_FILE_MODS=true` → install plugin via admin/WP-CLI bloquée → pose manuelle + `wp plugin activate`.
- Aucun plugin cache, pas de drop-in `object-cache.php`.

## Changements
1. `apt install php8.3-redis` → `systemctl restart php8.3-fpm`.
2. **Redis en mode cache** : `maxmemory 256mb`, `maxmemory-policy allkeys-lru` (évince au lieu d'échouer),
   persisté via `CONFIG REWRITE`.
3. Plugin **redis-cache** : téléchargé depuis wordpress.org dans `wp-content/plugins/`, `wp plugin activate redis-cache`.
4. `wp-config.php` (avant "stop editing") :
   ```php
   define( 'WP_REDIS_HOST', '127.0.0.1' );
   define( 'WP_REDIS_PORT', 6379 );
   define( 'WP_REDIS_DATABASE', 0 );
   define( 'WP_REDIS_PREFIX', 'tlo_' );
   define( 'WP_REDIS_MAXTTL', 86400 );
   define( 'WP_CACHE_KEY_SALT', 'tlo_les_orgues_' );
   ```
5. Activer le drop-in : `wp redis enable` (crée `wp-content/object-cache.php`).

## Sécurité / risque
- Redis localhost-only sans password = standard pour WP+Redis mono-serveur.
- Le drop-in tombe en cache non-persistant si Redis est injoignable → **pas de panne** si Redis down.
- Réversible : `wp redis disable` (retire le drop-in) + `wp plugin deactivate redis-cache`.

## Versioning
- Snapshot avant : `snapshots/wordpress/wp-config.before-redis.php` (mots de passe masqués)
- Backup serveur : `wp-config.php.bak-20260624-redis`
- Snapshot après : `redis-status.after.txt`

## Résultat (vérifié 2026-06-24)
- `php8.3-redis` installé, FPM redémarré, extension chargée.
- Redis en mode cache : `maxmemory 256mb`, `maxmemory-policy allkeys-lru` (persisté).
- Plugin `redis-cache` 2.8.0 actif, drop-in `object-cache.php` posé (chown www-data).
- `wp redis status` → **Connected / Drop-in Valid / Ping 1**.
- Cache actif : DBSIZE ~3455 clés, **20 000+ keyspace_hits**.

## ⚠️ Incident pendant l'activation : 504 Gateway Timeout (résolu)
**Symptôme** : après `wp redis enable` + warm loop, pool FPM saturé (`active:25 idle:0`,
"reached pm.max_children (25)") → Apache `AH01075 timeout` → 504.

**Cause racine (PAS Redis)** : la migration FPM (OPTIM-02) plafonnait à **25 workers**, alors que
`mpm_prefork` montait à ~150 par défaut. Pages lentes (~1.5s à chaud, boucle coûteuse de
`single-artiste.php` sur tous les posts) + flot de bots + cache froid → thundering herd → saturation.
Test : 1000 ops Redis = 615 ms (~0.6 ms/op) → Redis sain.

**Correctif** : `pm.max_children` 25 → **40**, `pm.max_requests = 500` (recyclage workers).
Vérif : 12 requêtes // → **12× 200, zéro 504**, FPM revient idle, plus aucun timeout proxy.

> **Leçon** : sous FPM il faut dimensionner `max_children` selon le débit réel (bots inclus).
> **Implication** : le **cache de page** (couche suivante) devient prioritaire — il sert les pages
> lentes aux anonymes/bots en ~50 ms et élimine le risque de saturation FPM.

## Statut : ✅ APPLIQUÉ (avec retune FPM max_children=40)
