Redis: O padrão da indústria
Arquitetura do Redis
Entenda a arquitetura interna, modelo single-thread, estruturas de dados e gerenciamento de memória do Redis.
Nesta aula você vai
- Descrever o modelo single-threaded do Redis e suas implicações de performance
- Explicar o protocolo RESP e o ciclo comando-resposta do servidor
- Mapear componentes internos: event loop, dict, expiração e alocação de memória
Arquitetura do Redis
Objetivos
Nesta aula você vai:
- Compreender como o Redis processa conexões e comandos internamente
- Entender por que o modelo single-threaded não impede alto throughput
- Identificar gargalos reais: rede, memória, comandos O(N) e persistência
Introdução
Redis parece um servidor monolítico simples — e, em muitos aspectos, é deliberadamente assim. Por baixo do redis-cli, porém, há um event loop baseado em epoll/kqueue, um protocolo binário-texto híbrido chamado RESP, e estruturas C altamente otimizadas (dict, quicklist, intset, skiplist). Conhecer essa arquitetura evita mitos ("preciso de mais threads no Redis") e orienta tuning em produção.
Conteúdo
Visão geral do processo servidor
Um nó Redis típico executa um único processo principal que:
- Aceita conexões TCP (porta 6379 por padrão)
- Lê comandos no protocolo RESP
- Executa o comando na estrutura de dados em memória
- Enfileira resposta no buffer do cliente
- Repete, intercalando tarefas de background (AOF fsync, expiração lazy/active)
Cliente ──TCP/RESP──► [ Event Loop ] ──► Dict de chaves
│
├──► Expiration (passive/active)
├──► Replication buffer → réplicas
└──► AOF/RDB (threads auxiliares em versões recentes)
A partir do Redis 6+, I/O threads opcionais paralelizam leitura/escrita de rede; o núcleo de execução de comandos permanece single-threaded por instância — decisão de design para evitar locks em estruturas compartilhadas.
Protocolo RESP (REdis Serialization Protocol)
RESP tipifica mensagens em tipos simples:
| Prefixo | Tipo | Exemplo |
|---|---|---|
+ |
Simple string | +OK |
- |
Error | -ERR unknown command |
: |
Integer | :1000 |
$ |
Bulk string | $5\r\nhello |
* |
Array | *2\r\n$3\r\nGET\r\n$3\r\nkey |
O cliente envia arrays de bulk strings; o servidor responde conforme o comando. Essa simplicidade permitiu clientes em dezenas de linguagens com parsing mínimo.
Exemplo manual equivalente a SET chave valor:
redis-cli --raw
Internamente, redis-cli serializa *3\r\n$3\r\nSET\r\n$5\r\nchave\r\n$5\r\nvalor\r\n.
Modelo de memória e chaves
Cada chave vive em um dict (hash table). O valor é um redisObject com tipo (string, list, hash, set, zset, stream…) e encoding interno que pode mudar conforme tamanho (ex.: ziplist → hashtable após limiar).
Políticas importantes:
- maxmemory: teto de RAM; acima disso, eviction conforme política (
volatile-lru,allkeys-lfu, etc.) - active expire: amostragem periódica remove chaves com TTL vencido
- lazy free: liberação assíncrona de objetos grandes (
UNLINKvsDEL)
Por que single-threaded escala?
Operações em RAM são microssegundos. Um core moderno pode executar centenas de milhares de comandos simples por segundo. O gargalo costuma ser:
- Latência de rede entre app e Redis
- Comandos O(N) (
KEYS *,SMEMBERSem set enorme) - Valores grandes — serialização e banda
- Persistência síncrona —
appendfsync always - Muitas conexões mal gerenciadas (use connection pool)
Paralelismo horizontal vem de múltiplas instâncias ou Cluster, não de threads competindo pelo mesmo dict.
Módulos e extensibilidade
Redis suporta módulos dinâmicos (RedisJSON, RediSearch, RedisBloom…) carregados em runtime. Eles estendem o servidor com novos comandos e tipos, mantendo o event loop. Em arquiteturas que dependem de busca full-text ou JSON nativo, módulos reduzem round-trips à aplicação — com custo de memória e complexidade operacional adicional.
Exemplos práticos
Inspecionar configuração e role do nó:
redis-cli INFO server
redis-cli CONFIG GET io-threads
redis-cli CONFIG GET maxmemory-policy
Medir custo de comando perigoso vs alternativa:
# Evite em produção — O(N) em todas as chaves
KEYS *
# Prefira iteração incremental
SCAN 0 MATCH user:* COUNT 100
Monitorar comandos lentos:
CONFIG SET slowlog-log-slower-than 10000
SLOWLOG GET 10
Slowlog registra comandos acima de 10 ms (10 000 µs) — ferramenta essencial para diagnosticar arquitetura mal utilizada.
Resumo
- Redis usa event loop single-threaded para execução de comandos, com I/O threads opcionais e workers para persistência.
- RESP é protocolo simples cliente-servidor que alimenta todo o ecossistema de clientes.
- Dados organizam-se em dict com encodings adaptativos e políticas de memória/eviction.
- Performance limita-se mais por rede, comandos O(N) e persistência do que por falta de threads.
- SCAN, connection pooling e dimensionamento horizontal são respostas arquiteturais corretas — não "um Redis maior" sem análise.