Organizando o uso de cache com Redis na sua aplicação

Organizando o uso de cache com Redis na sua aplicação
Organizando o uso de cache com Redis na sua aplicação.

O Redis é uma excelente solução de cache em memória, usado para acelerar respostas e aliviar a carga no banco de dados. Mas com grandes poderes vêm grandes responsabilidades: mal gerenciado, ele pode ser um vilão em vez de herói.

Estrutura básica da aplicação com Redis

Hoje uso um padrão simples e eficaz:

  1. Admin atualiza os dados (ex: categorias):
    • O back-end salva no banco e invalida o cache correspondente no Redis.
  2. Front-end faz a leitura:
    • Primeira tentativa: busca no Redis.
    • Se não encontrar, consulta o banco e popula o Redis com o resultado.

Esse padrão é conhecido como cache-aside (lazy loading).

Vantagens dessa abordagem

  • Evita dados desatualizados: só lê do Redis se estiver lá, senão pega do banco e atualiza o cache.
  • Desacoplamento: o front e o Redis não precisam saber quando os dados mudam. O admin dispara a invalidação.
  • Economia de recursos do banco: leitura massiva é desviada pro Redis.

Quando usar cache (ou não)

Saber o que cachear é tão importante quanto saber como.

🔁 Quando usar Redis (boas situações)

  • Dados lidos com muita frequência e que mudam com pouca frequência.
    Ex: lista de categorias, banners, configurações públicas do app.
  • Respostas pesadas ou com custo alto de geração.
    Ex: joins complexos, agregações, chamadas externas.
  • Sessões de usuário ou carrinhos temporários.
  • Dados de lookup rápido, como status, configs, permissões.

🚫 Evite usar Redis quando:

  • O dado muda com muita frequência e precisa estar sempre consistente.
    Ex: saldo bancário, estoque em tempo real.
  • A estrutura muda o tempo todo e a invalidação seria mais cara que o ganho.
  • O dado é muito grande (grandes arrays ou documentos) e não tem acesso frequente.
  • Você não tem uma estratégia clara de expiração/invalidação.

Cuidados com a memória RAM

Redis armazena tudo em memória. Se não for controlado, pode:
  • Estourar o consumo do servidor.
  • Forçar o Redis a evitar chaves antigas, gerando falhas silenciosas.
  • Competir com sua aplicação ou banco de dados por recursos.

Boas práticas:

  • Defina TTL (tempo de expiração) nas chaves.
  • Utilize prefixos organizados, como category:list, product:123.
  • Monitore o uso com INFO MEMORY e KEYS.

Código exemplo (TypeScript + Redis)

// Cache helper
const getCache = async (key: string) => {
  const data = await redis.get(key)
  return data ? JSON.parse(data) : null
}

const setCache = async (key: string, data: any, ttl = 3600) => {
  await redis.set(key, JSON.stringify(data), 'EX', ttl)
}

// Exemplo de leitura no front
export const getCategories = async () => {
  const key = RedisKeys.CATEGORY.LIST
  const cached = await getCache(key)
  if (cached) return cached

  const categories = await db.getCategories()
  await setCache(key, categories)
  return categories
}

Invalidação no admin

export const updateCategory = async (id, payload) => {
  await db.updateCategory(id, payload)
  await redis.del(RedisKeys.CATEGORY.LIST) // Invalida a lista
}

Organização das chaves do Redis

Para manter o código limpo e evitar duplicações ou erros de digitação, centralize as chaves em um arquivo.

Exemplo: src/cache/redisKeys.ts

export const RedisKeys = {
  CATEGORY: {
    LIST: 'category:list',
    DETAILS: (id: string) => `category:details:${id}`,
  },
  PRODUCT: {
    DETAILS: (id: string) => `product:details:${id}`,
    STOCK: (sku: string) => `product:stock:${sku}`,
  },
  USER: {
    SESSION: (id: string) => `user:session:${id}`,
    CART: (id: string) => `user:cart:${id}`,
  },
}

Usar Redis é poderoso, mas exige disciplina e estratégia. Saber o que cachear, quando invalidar e como gerenciar a memória são decisões cruciais para não transformar performance em problema.
E lembre-se: uma boa organização das chaves é meio caminho andado para um cache confiável e sustentável.