Mise en cache en Go : Redis, Memcached et solutions intégrées : de A à Z
\n\nLa mise en cache est l’un des outils clés pour améliorer les performances des applications web et des microservices. En Go (Golang), il existe de nombreuses approches : des simples cartes en mémoire aux systèmes distribués puissants comme Redis et Memcached. Dans cet article, nous allons passer en revue toutes les options populaires de mise en cache en Go avec des exemples de code, comparer leurs performances et montrer les meilleures pratiques de mise en œuvre.
\n\nPourquoi la mise en cache en Go est-elle nécessaire ?
\nSans cache, chaque accès aux données peut entraîner des opérations coûteuses : requêtes à la base de données, appels à des API externes ou calculs complexes. La mise en cache permet de sauvegarder le résultat de la première opération et de le restituer rapidement lors des requêtes suivantes. Cela réduit la charge sur le backend, diminue les latences et améliore l’expérience utilisateur. En Go, grâce aux goroutines et à la haute concurrence, une implémentation correcte du cache est particulièrement importante.
\n\n1. Solutions intégrées : sync.Map et bigcache
\nPour les petits projets ou les cas où la distribution n’est pas nécessaire, Go propose des mécanismes de mise en cache intégrés.
\n\n1.1 sync.Map
\nsync.Map est une carte thread-safe de la bibliothèque standard de Go. Elle est optimisée pour les cas où les clés sont écrites une fois et lues plusieurs fois. Idéale pour les caches à faible fréquence de mise à jour.
package 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 cache.Store("user:2", "Bob")\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:2")\n\n // Itération (Range)\n cache.Range(func(key, value interface{}) bool {\n fmt.Printf("Clé : %v, Valeur : %v\\n", key, value)\n return true\n })\n}\nAvantages : aucune dépendance externe, API simple, thread-safe.
\nInconvénients : pas de TTL (durée de vie), pas de limite de taille, performances réduites en cas d’écritures fréquentes.
1.2 BigCache
\nBigCache est une bibliothèque de mise en cache en mémoire rapide, spécialement conçue pour Go. Elle minimise les allocations mémoire et prend en charge le TTL.
\npackage main\n\nimport (\n "fmt"\n "time"\n "github.com/allegro/bigcache/v3"\n)\n\nfunc main() {\n config := bigcache.Config{\n Shards: 1024,\n LifeWindow: 10 * time.Minute,\n CleanWindow: 5 * time.Minute,\n MaxEntriesInWindow: 1000,\n MaxEntrySize: 500,\n Verbose: true,\n }\n\n cache, err := bigcache.NewBigCache(config)\n if err != nil {\n panic(err)\n }\n\n // Écriture\n cache.Set("session:abc123", []byte("user_data"))\n\n // Lecture\n data, err := cache.Get("session:abc123")\n if err == nil {\n fmt.Println("Données :", string(data))\n }\n}\nAvantages : haute vitesse, prise en charge du TTL, faible charge sur le GC (Garbage Collector).
\nInconvénients : uniquement pour une seule instance d’application, pas de réplication.
2. Memcached en Go
\nMemcached est un système de mise en cache distribué en mémoire. Il est simple, mais très rapide et prend en charge le TTL. En Go, le pilote github.com/bradfitz/gomemcache/memcache est utilisé pour interagir avec Memcached.
package main\n\nimport (\n "fmt"\n "github.com/bradfitz/gomemcache/memcache"\n)\n\nfunc main() {\n mc := memcache.New("127.0.0.1:11211")\n\n // Écriture\n err := mc.Set(&memcache.Item{\n Key: "user:42",\n Value: []byte("John Doe"),\n Expiration: 300, // 5 minutes\n })\n if err != nil {\n panic(err)\n }\n\n // Lecture\n item, err := mc.Get("user:42")\n if err == nil {\n fmt.Println("Valeur :", string(item.Value))\n }\n\n // Sup