# object-cache.php personnalisé : écrire son pont vers Redis Cluster

> Les extensions de cache d'objet grand public ne supportent pas toujours Redis Cluster. On documente l'écriture d'un drop-in object-cache.php maison pour un site à très fort trafic.

- Auteur : Clément Hadrot
- Publié le : 2026-02-27
- Mis à jour le : 2026-02-27
- Catégorie : Performance
- URL : https://wpmoderne.dev.wordpress-developpement.fr/performance/object-cache-php-personnalise-redis-cluster/

## L’essentiel

- Un drop-in remplace entièrement l'implémentation de cache d'objet de WordPress
- Le hachage de clés doit respecter les slots de Redis Cluster pour les opérations multi-clés
- Les groupes non persistants doivent rester en mémoire locale, jamais sur le cluster

Le site est celui d'une plateforme de billetterie en marque blanche, utilisée par plusieurs centaines de sites WordPress clients partageant une infrastructure Redis mutualisée sous forme de cluster à six nœuds, pour des raisons de disponibilité et de répartition de charge décidées par l'équipe infrastructure indépendamment du choix applicatif WordPress. Les extensions de cache d'objet Redis les plus répandues dans l'écosystème WordPress, à l'époque de ce projet, ne prenaient en charge qu'une instance Redis unique ou une configuration maître-esclave classique, pas le mode cluster avec ses contraintes propres de répartition des clés en slots.

## Pourquoi un drop-in maison plutôt qu'une extension existante

Un fichier `object-cache.php` placé dans `wp-content` est un « drop-in » : WordPress le charge automatiquement et l'utilise à la place de son implémentation de cache d'objet par défaut (qui se contente de la mémoire du processus PHP), sans qu'aucune activation d'extension ne soit nécessaire. Faute d'extension existante gérant Redis Cluster de façon satisfaisante à l'époque, et face à un volume de trafic qui rendait l'absence de cache d'objet persistant simplement inenvisageable, l'équipe a choisi d'écrire son propre pont, en s'appuyant sur l'extension PHP native `phpredis` compilée avec le support cluster.

## La contrainte principale : les slots de hachage

Redis Cluster répartit les clés entre les nœuds selon un hachage CRC16 modulo 16384, organisé en « slots ». Une opération portant sur plusieurs clés à la fois (comme un `MGET`) échoue si les clés concernées ne se trouvent pas sur le même nœud, sauf à utiliser des « hash tags » — une partie de la clé entre accolades qui force son affectation à un slot donné, indépendamment du reste de la clé.

> L'essentiel à retenir : Un drop-in remplace entièrement l'implémentation de cache d'objet de WordPress ; Le hachage de clés doit respecter les slots de Redis Cluster pour les opérations multi-clés ; Les groupes non persistants doivent rester en mémoire locale, jamais sur le cluster

```
┌───────────────────────────────────────────────┐
│  WordPress (wp_cache_get / wp_cache_set)        │
└───────────────────┬─────────────────────────────┘
                     │
                     ▼
┌───────────────────────────────────────────────┐
│  object-cache.php (pont maison, phpredis cluster)│
│  - regroupe la clé + le groupe en hash tag       │
│  - sépare groupes persistants / non persistants  │
└───────────────────┬─────────────────────────────┘
                     │
        ┌────────────┼────────────┬────────────┐
        ▼            ▼            ▼            ▼
   Nœud Redis 1  Nœud Redis 2  Nœud Redis 3  ...jusqu'à 6
```

## Construction de la clé avec hash tag

Le pont construit chaque clé de cache en intégrant le groupe WordPress dans un hash tag, ce qui garantit que toutes les clés d'un même groupe (par exemple toutes les métadonnées d'un même site en configuration multisite) tombent sur le même nœud, rendant possibles les opérations groupées quand elles sont nécessaires.

```
class Redis_Cluster_Object_Cache {

    private $redis;

    public function __construct() {
        $this->redis = new RedisCluster(
            null,
            [ 'redis-node-1:6379', 'redis-node-2:6379', 'redis-node-3:6379' ],
            1.5,   // timeout
            1.5,   // timeout de lecture
            true,  // persistent
            REDIS_CLUSTER_AUTH
        );
    }

    private function construire_cle( $cle, $groupe ) {
        // Le hash tag {groupe} force toutes les clés du même groupe sur le même nœud
        return "{{$groupe}}:{$cle}";
    }

    public function get( $cle, $groupe = 'default' ) {
        $valeur = $this->redis->get( $this->construire_cle( $cle, $groupe ) );
        return false === $valeur ? false : maybe_unserialize( $valeur );
    }

    public function set( $cle, $donnees, $groupe = 'default', $expiration = 0 ) {
        $valeur = maybe_serialize( $donnees );
        if ( $expiration > 0 ) {
            return $this->redis->setex( $this->construire_cle( $cle, $groupe ), $expiration, $valeur );
        }
        return $this->redis->set( $this->construire_cle( $cle, $groupe ), $valeur );
    }
}
```

## Les groupes non persistants ne doivent jamais toucher le cluster

WordPress distingue les groupes de cache « non persistants » (comme `counts` ou `plugins`), qui n'ont de sens que pour la durée d'une seule requête PHP et n'ont donc jamais besoin d'être partagés entre serveurs. Le pont maison garde une liste explicite de ces groupes et les traite entièrement en mémoire locale PHP (un simple tableau statique), sans jamais les envoyer au cluster Redis, ce qui évite un aller-retour réseau coûteux pour une donnée qui n'a de valeur que le temps d'une requête.

```
private $groupes_non_persistants = [ 'counts', 'plugins', 'themes' ];
private $cache_local = [];

public function get( $cle, $groupe = 'default' ) {
    if ( in_array( $groupe, $this->groupes_non_persistants, true ) ) {
        return $this->cache_local[ $groupe ][ $cle ] ?? false;
    }
    // ... sinon interroger le cluster Redis
}
```

## Gestion des pannes partielles du cluster

Un cluster Redis peut perdre un nœud sans devenir totalement indisponible si la réplication est configurée correctement, mais le pont doit gérer ce cas sans faire planter WordPress : chaque appel réseau est encadré d'un bloc `try/catch` qui, en cas d'exception `RedisClusterException`, retourne `false` comme le ferait un cache miss normal, laissant WordPress se rabattre sur la base de données plutôt que d'afficher une erreur fatale au visiteur.

## Limites de cette approche

Ce pont maison a demandé environ trois semaines de développement et de tests de charge avant sa mise en production, un investissement qui ne se justifie que pour un projet où le volume de trafic et la mutualisation de l'infrastructure Redis rendent une extension grand public insuffisante. Cet article ne traite pas la configuration du cluster Redis lui-même côté serveur (nombre de nœuds, réplication, sharding), qui relève d'une décision d'infrastructure préalable et indépendante de ce pont applicatif.

> Écrire son propre drop-in de cache d'objet n'est jamais un objectif en soi ; c'est un dernier recours quand l'écosystème existant ne couvre pas une contrainte d'infrastructure déjà actée ailleurs dans l'entreprise.

## En résumé

Le pont maison a permis d'exploiter un cluster Redis à six nœuds déjà mutualisé par l'équipe infrastructure, sans dépendre d'une extension tierce alors incapable de gérer le mode cluster. La clé de voûte technique reste le hash tag sur le groupe de cache, qui garantit la cohérence des opérations multi-clés, combiné à un traitement local strict des groupes non persistants pour ne pas alourdir inutilement le trafic réseau vers le cluster.
