KeyDB
Multithreading no KeyDB
Entenda como o KeyDB paraleliza workers, gerencia locks e configura threads para extrair desempenho sem corromper dados.
Nesta aula você vai
- Descrever o modelo de threads do KeyDB e a distribuição de conexões
- Configurar parâmetros de multithreading para diferentes perfis de hardware
- Identificar padrões de carga que se beneficiam ou sofrem com o paralelismo
Multithreading no KeyDB
Objetivos
Nesta aula você vai:
- Compreender como o KeyDB divide conexões entre worker threads
- Ajustar configurações de thread para o seu hardware
- Reconhecer limitações herdadas do modelo Redis sob paralelismo
Introdução
Um romance em primeira pessoa tem um narrador; um em terceira pessoa omnisciente tem vários olhos sobre a mesma cidade. O KeyDB escolheu a segunda abordagem: múltiplos narradores (threads) observam bairros diferentes do mesmo banco de dados — mas certas ruas (chaves) ainda exigem que apenas um narrador escreva de cada vez.
Entender essa coreografia é essencial. Multithread sem disciplina produz corrida de dados; multithread com regras claras produz throughput. Esta aula ensina as regras do KeyDB.
Conteúdo
Arquitetura de threads
O KeyDB utiliza um modelo híbrido:
- Thread principal — coordenação, algumas operações globais
- Worker threads — processam comandos de conexões atribuídas
- Threads de I/O (conforme versão/config) — leitura/escrita de rede
Cada conexão de cliente é associada a um worker. Comandos daquela conexão executam serialmente naquela conexão — preservando semântica esperada por clientes que enviam pipeline na mesma sessão.
Conexão A ──► Worker 1 ──► Comandos serializados
Conexão B ──► Worker 2 ──► Comandos serializados
Conexão C ──► Worker 1 ──► Compartilha fila com A
Paralelismo real ocorre entre conexões em workers diferentes — não dentro de uma única conexão pipelined.
Locks e o fantasma do Redis
Por ser fork do Redis, o KeyDB herda estruturas de dados protegidas por locks quando múltiplos workers acessam estruturas compartilhadas. A implementação evoluiu para lock-free ou fine-grained locking em caminhos críticos, mas operações que tocam estado global ainda serializam.
| Operação | Paralelismo |
|---|---|
GET/SET em chaves distintas |
Alto — workers independentes |
INCR na mesma chave de conexões diferentes |
Moderado — lock na chave |
KEYS *, FLUSHALL |
Baixo — impacto global |
| Script Lua longo | Bloqueia worker associado |
MULTI/EXEC |
Atômico na conexão; locks entre workers se multi-key |
Configuração prática
Parâmetros comuns no keydb.conf:
# Número de threads de servidor (workers)
server-threads 4
# Threads de I/O para leitura de rede (se disponível na versão)
# io-threads 2
Regra prática inicial:
| Núcleos CPU | server-threads sugerido |
|---|---|
| 4 | 2–4 |
| 8 | 4–6 |
| 16+ | 8–12 (medir, não maximizar cegamente) |
Mais threads ≠ mais performance. Contenção de locks, cache inválido e context switching podem reduzir throughput além de um ponto ótimo. Benchmark com redis-benchmark ou memtier_benchmark em degraus: 2, 4, 8, 12 threads.
Conexões de cliente e pool
Aplicações com poucas conexões (pool pequeno) subutilizam workers. Se toda carga passa por 2 conexões Lettuce, dois workers trabalham e o resto descansa.
Recomendações:
- Pool de conexões proporcional a workers (ex.: 1–2 conexões por worker)
- Evite conexão única com pipeline massivo como única estratégia de throughput
- Em microserviços, some conexões de todos os pods — mil conexões ociosas consomem RAM
# Exemplo Spring Boot — ajuste conforme workers do KeyDB
spring.data.redis.lettuce.pool.max-active: 16
spring.data.redis.lettuce.pool.max-idle: 8
Comparando com Redis I/O threads
Redis 6+ introduziu I/O threads que paralelizam leitura/escrita de rede, mas o processamento de comandos permanece single-thread. KeyDB paraleliza execução — diferença fundamental.
| Recurso | Redis + I/O threads | KeyDB |
|---|---|---|
| Paralelismo de rede | Sim | Sim |
| Paralelismo de comandos | Não | Sim |
| Ganho em CPU-bound | Limitado | Significativo |
Se seu gargalo é parsing de protocolo e rede, I/O threads bastam. Se é execução de comandos, KeyDB ou DragonflyDB entram em cena.
Armadilhas comuns
- Hot key: milhares de clientes incrementando
counter:global— todos os workers disputam o mesmo lock - Script Lua monolítico: bloqueia worker por milissegundos; outros comandos na mesma conexão esperam
- Excesso de threads: contenção supera ganho
- Assumir linearidade: dobrar threads raramente dobra QPS
Monitore INFO stats, latência p99 e CPU por núcleo. Todos os núcleos em 100% com latência alta pode indicar contenção, não eficiência.
Resumo
- KeyDB distribui conexões entre worker threads; comandos na mesma conexão permanecem serializados
- Configure
server-threadsproporcional ao hardware e valide com benchmark incremental - Pool de conexões do cliente deve alimentar múltiplos workers para maximizar paralelismo
- Hot keys, scripts longos e operações globais limitam ganhos — problema compartilhado com qualquer store multithread
- KeyDB vai além dos I/O threads do Redis ao paralelizar execução de comandos, não apenas rede