Caché en Go (Golang): Redis, in-memory y otras soluciones
El caché es una de las estrategias clave para mejorar el rendimiento y reducir la carga en las bases de datos en aplicaciones Go. En este artículo, exploraremos los principales enfoques y bibliotecas para implementar el caché: desde soluciones simples in-memory hasta caché distribuido basado en Redis. Aprenderá cuándo elegir cada herramienta y cómo organizar correctamente el caché en proyectos Go.
1. Capacidades integradas: map y sync.Map
La forma más simple de caché en Go es usar un map normal con un mutex o el sync.Map seguro para concurrencia. Estos enfoques son adecuados para proyectos pequeños o prototipos donde no se requiere una política compleja de invalidación.
Ejemplo con sync.Map:
package main
import ( "fmt" "sync")
type Cache struct { data sync.Map}
func (c *Cache) Set(key string, value interface{}) { c.data.Store(key, value)}
func (c *Cache) Get(key string) (interface{}, bool) { return c.data.Load(key)}
func main() { cache := &Cache{} cache.Set("user:1", "Alice") if val, ok := cache.Get("user:1"); ok { fmt.Println("Encontrado:", val) }}Ventajas: simplicidad, cero dependencias.
Desventajas: sin TTL, sin limpieza automática, memoria ilimitada.
2. Caché in-memory con TTL: freecache
Freecache es una biblioteca rápida de caché in-memory con soporte para TTL (tiempo de vida de las entradas). Utiliza una arquitectura segmentada para minimizar los bloqueos y gestiona la memoria de manera eficiente.
Instalación:
go get github.com/coocood/freecacheEjemplo de uso:
package main
import ( "fmt" "github.com/coocood/freecache")
func main() { // Creamos un caché de 100 MB cache := freecache.NewCache(100 * 1024 * 1024)
// Establecemos un valor con TTL de 10 segundos cache.Set([]byte("mikey"), []byte("mivalor"), 10)
// Obtenemos el valor if val, err := cache.Get([]byte("mikey")); err == nil { fmt.Println("Valor:", string(val)) } else { fmt.Println("Clave no encontrada o expirada") }}Ventajas: limpieza automática por TTL, bajo consumo de CPU, soporte para grandes volúmenes de datos.
Desventajas: solo para un proceso (no distribuido).
3. BigCache — alternativa a freecache
BigCache es otra biblioteca popular de caché in-memory, optimizada para almacenar una gran cantidad de entradas (millones) con un tiempo de acceso mínimo. También admite TTL y evacuación automática de datos antiguos.
Ejemplo:
package main
import ( "fmt" "github.com/allegro/bigcache/v3" "time")
func main() { config := bigcache.Config{ Shards: 1024, LifeWindow: 10 * time.Minute, CleanWindow: 5 * time.Minute, MaxEntriesInWindow: 1000 * 10 * 60, MaxEntrySize: 500, Verbose: true, }
cache, _ := bigcache.NewBigCache(config) cache.Set("mikey", []byte("valor bigcache")) val, _ := cache.Get("mikey") fmt.Println(string(val))}Ventajas: alto rendimiento con gran cantidad de claves, configuración flexible.
Desventajas: al igual que freecache, es un caché local.
4. Caché distribuido con Redis y go-redis
Para sistemas distribuidos donde varias instancias de la aplicación deben compartir un caché unificado, se utiliza Redis. El cliente más popular para Go es go-redis (anteriormente go-redis/redis).
Instalación:
go get github.com/redis/go-redis/v9Ejemplo de caché básico:
También en la biblioteca
Lodash para JavaScript (Node.js): guía completa con ejemplos
Cliente Elasticsearch para Swift (iOS/macOS): integración y ejemplos
Análisis de HTML en C# (.NET): bibliotecas HtmlAgilityPack y AngleSharp
RxJava para Java: guía completa con ejemplos prácticos