Introducción: ¿Por qué necesitas caché en Go a nivel avanzado?
En sistemas de alta carga en Go (Golang), la velocidad de acceso a los datos a menudo se convierte en un cuello de botella. La base de datos no siempre puede procesar miles de solicitudes por segundo sin retrasos significativos. El caché es una herramienta clave para reducir la carga en la base de datos y acelerar la respuesta de la API.
A nivel inicial, los desarrolladores suelen usar map simples con mutex. Sin embargo, en producción se requieren soluciones más avanzadas: cachés distribuidos (Redis, Memcached) y bibliotecas in-memory de alto rendimiento (BigCache, FreeCache). En este artículo, analizaremos sus características, compararemos el rendimiento y mostraremos ejemplos de código en Go para cada opción.
1. Soluciones integradas: sync.Map y las bibliotecas BigCache/FreeCache
1.1. sync.Map — cuando no necesitas una dependencia externa
El paquete sync.Map es un map seguro para concurrencia, optimizado para escenarios donde las claves se escriben una vez y se leen muchas veces. No requiere bloqueos en lectura, lo que proporciona un aumento de rendimiento.
Ejemplo de uso:
package main
import ( "fmt" "sync")
func main() { var cache sync.Map
// Escritura cache.Store("user:1", "Alice")
// Lectura if value, ok := cache.Load("user:1"); ok { fmt.Println("Encontrado:", value) }
// Eliminación cache.Delete("user:1")}Desventajas: no tiene invalidación automática por TTL, no tiene límite de memoria. Es adecuado para almacenamiento temporal de configuraciones o datos que cambian con poca frecuencia.
1.2. BigCache — caché in-memory rápido con TTL
BigCache de Allegro es una biblioteca que almacena datos en arreglos de bytes, evitando la sobrecarga del GC. Soporta TTL y evacuación automática de entradas antiguas.
Ejemplo:
import ( "github.com/allegro/bigcache/v3" "time")
func main() { cache, _ := bigcache.NewBigCache(bigcache.DefaultConfig(10 * time.Minute))
// Escritura cache.Set("mykey", []byte("myvalue"))
// Lectura entry, _ := cache.Get("mykey") println(string(entry))}Ventajas: presión mínima sobre el GC, alta velocidad (millones de operaciones por segundo). Desventajas: los datos se almacenan solo en bytes, no hay soporte para estructuras complejas sin serialización.
1.3. FreeCache — alternativa con tamaño fijo
FreeCache es otra biblioteca in-memory con tamaño de caché configurable. Utiliza segmentación para reducir los bloqueos.
import "github.com/coocood/freecache"
func main() { // Tamaño del caché — 100 MB cache := freecache.NewCache(100 * 1024 * 1024)
cache.Set([]byte("key"), []byte("value"), 60) // TTL 60 seg got, _ := cache.Get([]byte("key")) println(string(got))}2. Redis — caché distribuido con estructuras avanzadas
Redis es el caché externo más popular para aplicaciones Go. Soporta no solo cadenas, sino también listas, hashes, conjuntos, así como TTL, Pub/Sub y transacciones.
2.1. Conexión y operaciones básicas
Para trabajar con Redis en Go se utiliza el controlador go-redis/redis (o redis/v8).
import ( "github.com/go-redis/redis/v8" "context")
var ctx = context.Background()
func main() { rdb := redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", DB: 0, })
// Establecer con TTL de 10 segundos err := rdb.Set(ctx, "key", "value", 10*time.Second).Err() if err != nil { panic(err) }
val, err := rdb.Get(c