KeyDB

Multithreading no KeyDB

Entenda como o KeyDB paraleliza workers, gerencia locks e configura threads para extrair desempenho sem corromper dados.

Intermediário 42 min 32 pontos Leitura 0%

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:

  1. Thread principal — coordenação, algumas operações globais
  2. Worker threads — processam comandos de conexões atribuídas
  3. 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

  1. Hot key: milhares de clientes incrementando counter:global — todos os workers disputam o mesmo lock
  2. Script Lua monolítico: bloqueia worker por milissegundos; outros comandos na mesma conexão esperam
  3. Excesso de threads: contenção supera ganho
  4. 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-threads proporcional 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