Caché en Go: Redis, Memcached y soluciones integradas

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course
```html

Almacenamiento en caché en Go: Redis, Memcached y soluciones integradas



El almacenamiento en caché es una de las herramientas clave para mejorar el rendimiento de aplicaciones y servicios web. En el ecosistema de Go (Golang), el desarrollador tiene acceso tanto a sistemas de caché externos (Redis, Memcached) como a soluciones integradas como sync.Map o las bibliotecas bigcache y freecache. En este artículo, analizaremos los pros y los contras de cada enfoque, proporcionaremos ejemplos de código y ayudaremos a elegir la herramienta óptima para su proyecto.



1. Caché integrado: sync.Map y map con mutex



Go ofrece primitivas básicas para crear un caché directamente en la memoria de la aplicación. La forma más sencilla es usar un map normal con un mutex para la seguridad en concurrencia.



Ejemplo: caché simple seguro para concurrencia



package main

import ( "fmt" "sync" "time")

type Cache struct { mu sync.RWMutex items map[string]interface{}}

func NewCache() *Cache { return &Cache{ items: make(map[string]interface{}), }}

func (c *Cache) Set(key string, value interface{}) { c.mu.Lock() defer c.mu.Unlock() c.items[key] = value}

func (c *Cache) Get(key string) (interface{}, bool) { c.mu.RLock() defer c.mu.RUnlock() val, ok := c.items[key] return val, ok}

func main() { cache := NewCache() cache.Set("user:1", "Alice") val, _ := cache.Get("user:1") fmt.Println(val) // Alice}


Para escenarios más complejos, Go proporciona sync.Map — un mapa concurrente optimizado que es más adecuado para casos donde las claves se escriben una vez y se leen muchas veces.



¿Cuándo usar el caché integrado?

  • Micro-caché (durante una sola solicitud o sesión).
  • Aplicaciones singleton sin arquitectura distribuida.
  • Simplicidad — no es necesario levantar servicios externos.


Desventajas: falta de invalidación automática, tamaño limitado (depende de la memoria de la aplicación), sin persistencia.



2. BigCache y FreeCache: soluciones ligeras en memoria



Las bibliotecas bigcache y freecache resuelven el problema de la memoria limitada y el GC (recolección de basura). Utilizan búferes preasignados y minimizan la carga en el recolector de basura de Go.



Ejemplo con BigCache



package main

import ( "fmt" "github.com/allegro/bigcache/v3" "time")

func main() { cache, _ := bigcache.NewBigCache(bigcache.DefaultConfig(10 * time.Minute)) cache.Set("mykey", []byte("myvalue")) val, _ := cache.Get("mykey") fmt.Println(string(val)) // myvalue}


Ejemplo con FreeCache



package main

import ( "fmt" "github.com/coocood/freecache")

func main() { cache := freecache.NewCache(100 * 1024) // 100 KB cache.Set([]byte("key"), []byte("value"), 60) // TTL 60 seg val, _ := cache.Get([]byte("key")) fmt.Println(string(val)) // value}


Ambas bibliotecas admiten TTL (tiempo de vida) y eliminación automática de entradas antiguas. BigCache es mejor para grandes volúmenes de datos (cientos de gigabytes), FreeCache es para escenarios con operaciones frecuentes de escritura/lectura.



3. Redis: caché distribuido para producción



Redis es la opción más popular para el almacenamiento en caché en proyectos Go. Funciona como un servidor independiente, admite estructuras de datos complejas, persistencia y agrupación en clústeres.



Conexión a Redis en Go



package main

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, })

err := rdb.Set(ctx, "key", "value", 0).Err() if err != nil { panic(err) }

val, err := rdb.Get(ctx, "key").Result() if err != nil { panic(err) } fmt.Println("key", val)}
```

Blogs

Book Recommendations