Introduction : Pourquoi la mise en cache en Go au niveau avancé ?
\n\nDans les systèmes à forte charge en Go (Golang), la vitesse d'accès aux données devient souvent un goulot d'étranglement. La base de données n'est pas toujours capable de traiter des milliers de requêtes par seconde sans délais importants. La mise en cache est un outil clé pour réduire la charge sur la base de données et accélérer la réponse de l'API.
\n\nAu niveau débutant, les développeurs utilisent souvent de simples map avec des mutex. Cependant, en production, des solutions plus avancées sont nécessaires : des caches distribués (Redis, Memcached) et des bibliothèques en mémoire haute performance (BigCache, FreeCache). Dans cet article, nous analyserons leurs caractéristiques, comparerons leurs performances et montrerons des exemples de code en Go pour chaque option.
1. Solutions intégrées : sync.Map et les bibliothèques BigCache/FreeCache
\n\n1.1. sync.Map — quand aucune dépendance externe n'est nécessaire
\n\nLe paquet sync.Map est une map thread-safe, optimisée pour les scénarios où les clés sont écrites une fois et lues plusieurs fois. Il ne nécessite pas de verrous en lecture, ce qui améliore les performances.
Exemple d'utilisation :
\npackage main\n\nimport (\n "fmt"\n "sync"\n)\n\nfunc main() {\n var cache sync.Map\n\n // Écriture\n cache.Store("user:1", "Alice")\n\n // Lecture\n if value, ok := cache.Load("user:1"); ok {\n fmt.Println("Trouvé :", value)\n }\n\n // Suppression\n cache.Delete("user:1")\n}\n\nInconvénients : pas d'invalidation automatique avec TTL, pas de limite de mémoire. Convient au stockage temporaire de configurations ou de données rarement modifiées.
\n\n1.2. BigCache — cache en mémoire rapide avec TTL
\n\nBigCache d'Allegro est une bibliothèque qui stocke les données dans des tableaux d'octets, évitant les frais généraux du GC. Elle prend en charge le TTL et l'évacuation automatique des anciennes entrées.
\n\nExemple :
\nimport (\n "github.com/allegro/bigcache/v3"\n "time"\n)\n\nfunc main() {\n cache, _ := bigcache.NewBigCache(bigcache.DefaultConfig(10 * time.Minute))\n\n // Écriture\n cache.Set("mykey", []byte("myvalue"))\n\n // Lecture\n entry, _ := cache.Get("mykey")\n println(string(entry))\n}\n\nAvantages : pression minimale sur le GC, vitesse élevée (des millions d'opérations par seconde). Inconvénients : les données sont stockées uniquement en octets, pas de support pour les structures complexes sans sérialisation.
\n\n1.3. FreeCache — alternative avec taille fixe
\n\nFreeCache est une autre bibliothèque en mémoire avec une taille de cache configurable. Elle utilise le segmentation pour réduire les verrous.
\n\nimport "github.com/coocood/freecache"\n\nfunc main() {\n // Taille du cache — 100 Mo\n cache := freecache.NewCache(100 * 1024 * 1024)\n\n cache.Set([]byte("key"), []byte("value"), 60) // TTL 60 sec\n got, _ := cache.Get([]byte("key"))\n println(string(got))\n}\n\n2. Redis — mise en cache distribuée avec structures avancées
\n\nRedis est le cache externe le plus populaire pour les applications Go. Il prend en charge non seulement les chaînes, mais aussi les listes, les hachages, les ensembles, ainsi que le TTL, Pub/Sub et les transactions.
\n\n2.1. Connexion et opérations de base
\n\nPour travailler avec Redis en Go, on utilise le driver go-redis/redis (ou redis/v8).
import (\n "github.com/go-redis/redis/v8"\n "context"\n)\n\nvar ctx = context.Background()\n\nfunc main() {\n rdb := redis.NewClient(&redis.Options{\n Addr: "localhost:6379",\n Password: "",\n DB: 0,\n })\n\n // Définition avec TTL de 10 secondes\n err := rdb.Set(ctx, "key", "value", 10*time.Second).Err()\n if err != nil {\n panic(err)\n }\n\n val, err := rdb.Get(c