Introdução: Por que o cache é necessário em Go no nível avançado?
Em sistemas de alta carga em Go (Golang), a velocidade de acesso aos dados frequentemente se torna um gargalo. O banco de dados nem sempre consegue processar milhares de requisições por segundo sem atrasos significativos. O cache é uma ferramenta chave para reduzir a carga no banco de dados e acelerar a resposta da API.
No nível inicial, os desenvolvedores costumam usar map simples com mutexes. No entanto, em produção, são necessárias soluções mais avançadas: caches distribuídos (Redis, Memcached) e bibliotecas in-memory de alto desempenho (BigCache, FreeCache). Neste artigo, analisaremos suas características, compararemos o desempenho e mostraremos exemplos de código em Go para cada opção.
1. Soluções embutidas: sync.Map e bibliotecas BigCache/FreeCache
1.1. sync.Map — quando não é necessária uma dependência externa
O pacote sync.Map é um map thread-safe, otimizado para cenários onde as chaves são escritas uma vez e lidas muitas vezes. Ele não requer bloqueios na leitura, o que proporciona um ganho de desempenho.
Exemplo de uso:
package main
import ( "fmt" "sync")
func main() { var cache sync.Map
// Escrita cache.Store("user:1", "Alice")
// Leitura if value, ok := cache.Load("user:1"); ok { fmt.Println("Encontrado:", value) }
// Remoção cache.Delete("user:1")}Desvantagens: sem invalidação automática por TTL, sem limite de memória. Adequado para armazenamento temporário de configurações ou dados raramente alterados.
1.2. BigCache — cache in-memory rápido com TTL
BigCache da Allegro é uma biblioteca que armazena dados em arrays de bytes, evitando a sobrecarga do GC. Ela suporta TTL e evacuação automática de entradas antigas.
Exemplo:
import ( "github.com/allegro/bigcache/v3" "time")
func main() { cache, _ := bigcache.NewBigCache(bigcache.DefaultConfig(10 * time.Minute))
// Escrita cache.Set("mykey", []byte("myvalue"))
// Leitura entry, _ := cache.Get("mykey") println(string(entry))}Vantagens: pressão mínima sobre o GC, alta velocidade (milhões de operações por segundo). Desvantagens: dados armazenados apenas em bytes, sem suporte a estruturas complexas sem serialização.
1.3. FreeCache — alternativa com tamanho fixo
FreeCache é outra biblioteca in-memory com tamanho de cache configurável. Ela usa segmentação para reduzir bloqueios.
import "github.com/coocood/freecache"
func main() { // Tamanho do cache — 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 — cache distribuído com estruturas avançadas
Redis é o cache externo mais popular para aplicações Go. Ele suporta não apenas strings, mas também listas, hashes, conjuntos, além de TTL, Pub/Sub e transações.
2.1. Conexão e operações básicas
Para trabalhar com Redis em Go, utiliza-se o driver go-redis/redis (ou 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, })
// Configuração com TTL de 10 segundos err := rdb.Set(ctx, "key", "value", 10*time.Second).Err() if err != nil { panic(err) }
val, err := rdb.Get(c