Caching en Go (Golang): Redis y otras herramientas
El caching es uno de los mecanismos clave para optimizar el rendimiento de aplicaciones web y microservicios. En el ecosistema de Go (Golang), existen muchas bibliotecas para implementar caching, desde soluciones simples en memoria hasta sistemas distribuidos basados en Redis. En este artículo, analizaremos en detalle tres enfoques principales: estructuras de datos integradas (sync.Map), bibliotecas populares en memoria (go-cache, freecache, bigcache) y la integración con Redis.
1. Herramientas integradas: sync.Map
Go proporciona un map seguro para concurrencia — sync.Map. Es adecuado para caching simple con volúmenes de datos pequeños y actualizaciones poco frecuentes. Sin embargo, su rendimiento bajo cargas altas es inferior al de las bibliotecas especializadas.
Ejemplo de uso de sync.Map:
package main
import ( "fmt" "sync" "time")
func main() { var cache sync.Map
// Escritura cache.Store("user:42", map[string]interface{}{ "name": "Alice", "age": 30, })
// Lectura con verificación if val, ok := cache.Load("user:42"); ok { fmt.Println("Caché encontrado:", val) }
// Eliminación cache.Delete("user:42")
// Caching con TTL (debe implementarse manualmente) cache.Store("session:abc", time.Now().Unix())}Desventajas: falta de TTL automático, conjunto limitado de operaciones, posibles problemas de rendimiento con escrituras frecuentes.
2. Bibliotecas en memoria
Para escenarios más complejos, use bibliotecas especializadas. Consideremos tres populares:
2.1 go-cache
Biblioteca simple con soporte para TTL. Ideal para proyectos pequeños.
import "github.com/patrickmn/go-cache"
func main() { c := cache.New(5*time.Minute, 10*time.Minute) // TTL predeterminado, intervalo de limpieza
c.Set("key", "value", cache.DefaultExpiration) val, found := c.Get("key") if found { fmt.Println(val) }}2.2 freecache
Biblioteca con tamaño de memoria fijo (sin overhead de GC). Soporta TTL y alto rendimiento.
import "github.com/coocood/freecache"
func main() { cache := freecache.NewCache(100 * 1024 * 1024) // 100 MB
cache.Set([]byte("mykey"), []byte("myvalue"), 60) // TTL 60 seg val, err := cache.Get([]byte("mykey")) if err == nil { fmt.Println(string(val)) }}2.3 bigcache
Optimizada para almacenar grandes volúmenes de datos sin pausas de GC. Trabaja con datos serializados.
import "github.com/allegro/bigcache/v3"
func main() { cache, _ := bigcache.NewBigCache(bigcache.DefaultConfig(10 * time.Minute))
cache.Set("key", []byte("value")) val, _ := cache.Get("key") fmt.Println(string(val))}3. Redis: caching distribuido
Para sistemas distribuidos y microservicios, Redis sigue siendo el estándar de facto. En Go, use la biblioteca go-redis/redis (v9+).
Conexión y operaciones básicas:
import ( "context" "fmt" "github.com/redis/go-redis/v9")
func main() { ctx := context.Background() rdb := redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", DB: 0, })
// Establecer valor con TTL err := rdb.Set(ctx, "user:42", `{"name":"Bob"}`, 10*time.Minute).Err() if err != nil { panic(err) }
// Lectura val, err := rdb.Get(ctx, "user:42").Result() if err == redis.Nil { fmt.Println("Caché no encontrado") } else if err != nil { panic(err) } else { fmt.Println("Valor:", val) }}Funcionalidades avanzadas de Redis en Go:
- Pipeline
También en la biblioteca
Planificador de tareas Kotlin: descripción general y ejemplos de uso
Generación de PDF en TypeScript: revisión de bibliotecas y herramientas
Contenedores de Inyección de Dependencias en Rust: descripción general e implementación con el ejemplo de «dicy»
Event Bus y el patrón Observer en JavaScript (Node.js): implementación y ejemplos
Contenedor de Inyección de Dependencias para Swift (iOS/macOS): Swinject