Introdução ao Redis além do caching: pub/sub e filas

Quando se fala em Redis, a maioria dos desenvolvedores pensa imediatamente em caching. E com razão: sua capacidade de armazenar dados em memória com latência de microssegundos o tornou a escolha padrão para acelerar aplicações web. No entanto, reduzir o Redis a um simples cache é como usar um supercomputador apenas para calcular gorjetas. O Redis é, na verdade, uma plataforma de mensageria extremamente versátil, capaz de implementar padrões de comunicação como publish/subscribe (pub/sub) e filas de mensagens com desempenho impressionante.

Este artigo explora o Redis além do caching, mergulhando em seus recursos de mensageria — pub/sub, filas baseadas em listas e Redis Streams — com exemplos práticos que você pode implementar hoje mesmo.

1. Redis como plataforma de mensageria: conceitos fundamentais

1.1. Diferença entre caching e mensageria no ecossistema Redis

No caching, o Redis armazena dados para consulta futura, geralmente com um TTL (time-to-live). Na mensageria, o Redis atua como intermediário de comunicação entre processos ou serviços. Enquanto o caching é um padrão de armazenamento, a mensageria é um padrão de comunicação assíncrona.

1.2. Modelos de comunicação: publish/subscribe vs. filas

O Redis oferece três modelos principais de mensageria:

  • Pub/Sub: comunicação broadcast, onde mensagens são enviadas a todos os inscritos em um canal.
  • Listas (filas): comunicação ponto-a-ponto, onde cada mensagem é consumida por um único consumidor.
  • Streams: modelo híbrido que combina persistência com grupos de consumidores.

1.3. Casos de uso típicos

  • Pub/Sub: notificações em tempo real, atualizações de feed, chats ao vivo.
  • Filas com listas: processamento de tarefas em background, job queues.
  • Streams: sistemas de logs distribuídos, eventos de domínio, processamento em lote.

2. Pub/Sub no Redis: comunicação em tempo real

2.1. Estrutura de canais e padrões de inscrição

No pub/sub, o Redis gerencia canais. Um publisher envia mensagens para um canal, e todos os subscribers conectados àquele canal as recebem imediatamente.

# Terminal 1 - Subscriber
> SUBSCRIBE canal_notificacoes
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "canal_notificacoes"
3) (integer) 1

# Terminal 2 - Publisher
> PUBLISH canal_notificacoes "Novo usuário registrado"
(integer) 1

2.2. Limitações importantes

Pub/sub no Redis não persiste mensagens. Se um subscriber estiver offline no momento da publicação, a mensagem é perdida para sempre. Não há confirmação de entrega nem reenvio automático.

2.3. Exemplo prático: notificações em tempo real

# Publisher envia notificação de evento
PUBLISH eventos:pedidos "Pedido #1234 - Status: Entregue"

# Subscriber recebe e processa
SUBSCRIBE eventos:pedidos
1) "message"
2) "eventos:pedidos"
3) "Pedido #1234 - Status: Entregue"

3. Filas com listas Redis: padrão produtor-consumidor

3.1. Comandos LPUSH, RPUSH e bloqueio com BLPOP/BRPOP

Listas Redis são perfeitas para filas FIFO. Use LPUSH para adicionar tarefas e BRPOP para consumi-las com bloqueio, evitando polling constante.

# Produtor adiciona tarefa
LPUSH fila_tarefas "processar_pagamento:1234"

# Consumidor aguarda tarefa (bloqueante por 30 segundos)
BRPOP fila_tarefas 30
1) "fila_tarefas"
2) "processar_pagamento:1234"

3.2. Implementação de fila FIFO confiável com acknowledgments

Para garantir que tarefas não sejam perdidas em caso de falha do consumidor, use o padrão de "fila de trabalho" com listas auxiliares:

# Consumidor pega tarefa e move para fila "em processamento"
RPOPLPUSH fila_tarefas fila_processando

# Após processar com sucesso, remove da fila de processamento
LREM fila_processando 1 "processar_pagamento:1234"

# Se falhar, retorna para fila original
RPUSH fila_tarefas "processar_pagamento:1234"
LREM fila_processando 1 "processar_pagamento:1234"

3.3. Exemplo prático: processamento assíncrono de tarefas

# Produtor (API web)
LPUSH fila_envio_email "email:boas-vindas:user@exemplo.com"

# Consumidor (worker)
BRPOP fila_envio_email 0
# Processa envio de email...

4. Redis Streams: filas avançadas e persistência

4.1. Estrutura de streams, consumer groups e IDs automáticos

Redis Streams são a evolução das filas. Cada entrada tem um ID único (timestamp+sequencial) e múltiplos pares campo-valor.

# Adicionar entrada ao stream
XADD stream_pedidos * cliente "João" valor 150.00 produto "Livro"
"1728392012345-0"

# Ler entradas
XRANGE stream_pedidos - +
1) 1) "1728392012345-0"
   2) 1) "cliente"
      2) "João"
      3) "valor"
      4) "150.00"

4.2. Garantia de entrega com consumer groups

Consumer groups permitem que múltiplos consumidores processem mensagens de forma balanceada, com confirmação explícita.

# Criar grupo de consumidores
XGROUP CREATE stream_pedidos grupo_processamento $

# Consumidor 1 lê e confirma
XREADGROUP GROUP grupo_processamento consumidor1 COUNT 1 STREAMS stream_pedidos >
1) 1) "stream_pedidos"
   2) 1) 1) "1728392012345-0"
         2) 1) "cliente"
            2) "João"

# Confirmar processamento
XACK stream_pedidos grupo_processamento 1728392012345-0

4.3. Exemplo prático: sistema de logs distribuído

# Serviço A envia log
XADD logs_aplicacao * servico "auth" nivel "INFO" mensagem "Login bem-sucedido"

# Serviço de monitoramento consome
XREADGROUP GROUP grupo_monitor consumidor_logs COUNT 10 STREAMS logs_aplicacao >

5. Padrões de design com filas e pub/sub no Redis

5.1. Combinação de pub/sub com filas para notificações e processamento

Use pub/sub para notificar workers sobre novas tarefas e filas para o processamento real:

# Notificar workers sobre nova tarefa
PUBLISH canal_novas_tarefas "tarefa:123"

# Worker escuta notificação e busca tarefa da fila
SUBSCRIBE canal_novas_tarefas
# Ao receber: BRPOP fila_tarefas 0

5.2. Dead letter queues e retry mechanisms

Implemente filas de mensagens mortas para tarefas que falharam repetidamente:

# Após 3 falhas, move para dead letter queue
RPUSH fila_dlq "tarefa:123:falhou_3_vezes"

5.3. Estratégias de backpressure

Monitore o tamanho das filas com LLEN e implemente throttling no produtor quando a fila ultrapassar um limite.

6. Monitoramento e boas práticas operacionais

6.1. Métricas essenciais

# Tamanho da fila
LLEN fila_tarefas

# Latência do stream
XINFO STREAM stream_pedidos

# Número de mensagens não confirmadas
XPENDING stream_pedidos grupo_processamento

6.2. Configuração de memória e limpeza

Para streams, defina maxlen para evitar crescimento infinito:

XADD stream_pedidos MAXLEN ~10000 * cliente "Maria" valor 200

6.3. Segurança com ACLs

# Criar usuário com acesso restrito a pub/sub
ACL SETUSER worker on >senha_segura +@pubsub -@dangerous

7. Comparação com outras soluções de mensageria

7.1. Redis vs. RabbitMQ

RabbitMQ oferece roteamento avançado (exchanges, bindings) e entregas garantidas. Redis é mais simples e rápido, mas sem garantias de entrega no pub/sub.

7.2. Redis vs. Kafka

Kafka é projetado para retenção de longo prazo e replay de mensagens. Redis Streams oferecem baixa latência, mas com menor capacidade de armazenamento histórico.

7.3. Quando escolher cada modelo

  • Pub/sub Redis: notificações em tempo real onde perda de mensagens é aceitável.
  • Filas com listas: job queues simples e rápidas.
  • Redis Streams: sistemas que exigem persistência, grupos de consumidores e tolerância a falhas.
  • RabbitMQ/Kafka: quando você precisa de roteamento complexo ou retenção massiva de dados.

O Redis é muito mais que um cache. Com pub/sub, filas e streams, ele se torna uma plataforma de mensageria leve e de altíssimo desempenho, ideal para arquiteturas modernas de microsserviços. Comece pequeno, com filas simples, e evolua para streams quando precisar de robustez — o Redis cresce com você.

Referências