- Ajouter ADR-018 (librairies Go) dans TECHNICAL.md - Transformer Shared en menu dépliable dans mkdocs (cohérence avec autres domaines) - Corriger listes markdown (ajout lignes vides avant listes) - Corriger line breaks dans génération BDD (étapes "Et" sur nouvelles lignes) - Ajouter script fix-markdown-lists.sh pour corrections futures Impacte 86 fichiers de documentation et 164 fichiers BDD générés.
157 lines
6.0 KiB
Markdown
157 lines
6.0 KiB
Markdown
# ADR-021 : Solution de Cache
|
|
|
|
**Statut** : Accepté
|
|
**Date** : 2026-01-31
|
|
|
|
## Contexte
|
|
|
|
L'application nécessite un système de cache performant pour plusieurs cas d'usage critiques :
|
|
|
|
- **Cache de géolocalisation** : Requêtes de proximité géographique intensives (contenus à moins de X mètres)
|
|
- **Sessions utilisateurs** : Stockage temporaire des tokens JWT et contexte utilisateur
|
|
- **Données de référence** : Métadonnées des contenus audio fréquemment consultés
|
|
- **Compteurs en temps réel** : Nombre d'écoutes, statistiques d'engagement
|
|
- **Rate limiting** : Protection contre les abus API
|
|
|
|
Les contraintes de performance sont strictes :
|
|
|
|
- Latence p99 < 5ms pour les requêtes de cache
|
|
- Support de 100K+ requêtes/seconde en lecture
|
|
- Persistance optionnelle (données non critiques)
|
|
- Clustering pour haute disponibilité
|
|
|
|
## Décision
|
|
|
|
**Redis 7+ en mode Cluster** sera utilisé comme solution de cache principale.
|
|
|
|
Configuration :
|
|
|
|
- Mode Cluster avec 3 nœuds minimum (haute disponibilité)
|
|
- Persistence RDB désactivée pour les caches chauds (performance maximale)
|
|
- AOF activé uniquement pour les sessions utilisateurs (durabilité)
|
|
- Éviction `allkeys-lru` sur les caches non-critiques
|
|
|
|
## Alternatives considérées
|
|
|
|
| Critère | Redis | Memcached | KeyDB | Valkey |
|
|
|---------|-------|-----------|-------|--------|
|
|
| Géospatial natif | ✅ `GEORADIUS` | ❌ | ✅ | ✅ |
|
|
| Structures de données | ✅ Sets, Hashes, Sorted Sets | ❌ Clé-valeur simple | ✅ | ✅ |
|
|
| Clustering | ✅ Redis Cluster | ✅ Client-side | ✅ | ✅ |
|
|
| Pub/Sub | ✅ | ❌ | ✅ | ✅ |
|
|
| Écosystème Go | ✅ `go-redis/redis` | ⚠️ Limité | ✅ Compatible | ✅ Compatible |
|
|
| Maturité | ✅ Très mature | ✅ Mature | ⚠️ Fork récent | ⚠️ Fork très récent |
|
|
| License | ⚠️ RSALv2 / SSPLv1 | ✅ BSD | ✅ BSD | ✅ BSD |
|
|
|
|
**Memcached** : Écarté pour l'absence de fonctionnalités géospatiales natives et de structures de données avancées (pas de sets, hashes).
|
|
|
|
**KeyDB** : Fork multi-thread de Redis compatible API. Écarté par manque de maturité relative et d'écosystème comparé à Redis (moins de contributions, documentation).
|
|
|
|
**Valkey** : Fork Linux Foundation de Redis (2024). Trop récent pour production, écosystème en construction. À réévaluer en 2026.
|
|
|
|
## Justification
|
|
|
|
### Fonctionnalités géospatiales natives
|
|
|
|
Redis fournit des commandes géospatiales optimisées critiques pour RoadWave :
|
|
|
|
- `GEOADD` : Indexation de contenus géolocalisés
|
|
- `GEORADIUS` : Recherche par rayon (ex: contenus à moins de 5km)
|
|
- `GEODIST` : Calcul de distance entre deux points
|
|
|
|
Ces commandes permettent de servir les requêtes de proximité directement depuis le cache sans solliciter PostgreSQL/PostGIS, réduisant la latence de 50-80ms à <5ms.
|
|
|
|
### Structures de données riches
|
|
|
|
- **Hashes** : Métadonnées de contenus (titre, durée, URL HLS) → accès partiel efficace
|
|
- **Sets** : Listes de contenus par catégorie, gestion de favoris
|
|
- **Sorted Sets** : Classement par popularité, top écoutes hebdomadaires
|
|
- **Strings avec TTL** : Sessions utilisateurs avec expiration automatique
|
|
|
|
### Performance et scalabilité
|
|
|
|
- **Débit** : 100K+ ops/sec par nœud en lecture (benchmark Redis Labs)
|
|
- **Latence** : p99 < 1ms pour GET/SET simple
|
|
- **Clustering** : Partitionnement automatique des données sur 16384 hash slots
|
|
- **Réplication** : Read replicas pour scaling horizontal en lecture
|
|
|
|
### Écosystème Go
|
|
|
|
Librairie `go-redis/redis` (13K+ stars GitHub) :
|
|
|
|
- Support complet Redis Cluster
|
|
- Pipeline et transactions
|
|
- Context-aware (intégration Go idiomatique)
|
|
- Pooling de connexions automatique
|
|
|
|
### Pub/Sub pour temps réel
|
|
|
|
Support natif de messaging publish/subscribe pour :
|
|
|
|
- Notifications push (invalidation de cache)
|
|
- Événements temps réel (nouveau contenu géolocalisé)
|
|
- Coordination entre instances API (scaling horizontal)
|
|
|
|
## Conséquences
|
|
|
|
### Positives
|
|
|
|
- **Cache géospatial** : Réduction de charge PostgreSQL de ~70% sur requêtes de proximité
|
|
- **Latence** : p99 < 5ms pour requêtes de contenu en cache (vs ~50ms PostgreSQL)
|
|
- **Scaling horizontal** : Ajout de nœuds Redis transparent pour l'application
|
|
- **Polyvalence** : Un seul système pour cache, sessions, rate limiting, pub/sub
|
|
|
|
### Négatives
|
|
|
|
- **Complexité opérationnelle** : Cluster Redis nécessite monitoring (slots, rebalancing)
|
|
- **Persistance limitée** : RDB/AOF moins fiable que PostgreSQL → pas pour données critiques
|
|
- **Consommation mémoire** : Structures riches = overhead vs Memcached (~20% de RAM en plus)
|
|
|
|
### Stratégie de cache
|
|
|
|
**TTL par type de donnée** :
|
|
|
|
- Métadonnées de contenu : 15 minutes (mise à jour rare)
|
|
- Résultats géolocalisés : 5 minutes (contenus statiques géographiquement)
|
|
- Sessions utilisateurs : 24 heures (renouvellement automatique)
|
|
- Rate limiting : 1 minute (fenêtre glissante)
|
|
|
|
**Invalidation** :
|
|
|
|
- Publication de contenu → `DEL` métadonnées + publication Pub/Sub
|
|
- Modification géolocalisation → `GEOREM` puis `GEOADD`
|
|
- Logout utilisateur → `DEL` session
|
|
|
|
### Configuration production
|
|
|
|
**Cluster 3 nœuds** (minimum haute disponibilité) :
|
|
|
|
- 1 master + 2 replicas
|
|
- Répartition sur 3 zones de disponibilité (anti-affinité)
|
|
- `cluster-require-full-coverage no` → lecture dégradée si nœud down
|
|
|
|
**Mémoire** :
|
|
|
|
- `maxmemory 2gb` par nœud (ajustable selon charge)
|
|
- `maxmemory-policy allkeys-lru` → éviction automatique anciennes clés
|
|
|
|
**Persistance** :
|
|
|
|
- RDB désactivé (`save ""`) pour caches chauds
|
|
- AOF `appendonly yes` uniquement pour sessions (nœud dédié optionnel)
|
|
|
|
### Monitoring
|
|
|
|
Métriques critiques à suivre :
|
|
|
|
- Taux de hit/miss par namespace (target >95% hit rate)
|
|
- Latence p99 par commande (alerter si >10ms)
|
|
- Fragmentation mémoire (rebalance si >1.5)
|
|
- Slots distribution dans le cluster
|
|
|
|
## Références
|
|
|
|
- [Redis Geospatial Documentation](https://redis.io/docs/data-types/geospatial/)
|
|
- [go-redis/redis](https://github.com/redis/go-redis)
|
|
- [ADR-005 : Base de Données](./005-base-de-donnees.md) (architecture cache + PostgreSQL)
|