Por que o Redis está usando alta CPU? Técnicas de depuração e otimização
Investigue o uso repentino de alta CPU no Redis, um armazenamento de dados crítico em memória. Este guia detalha como depurar a carga usando os comandos `SLOWLOG` e `INFO` para identificar operações ineficientes como `KEYS *` ou exclusões de chaves grandes. Aprenda técnicas práticas de otimização, incluindo a mudança para `UNLINK` assíncrono, utilização de pipelining e ajuste das configurações de persistência, para reduzir imediatamente a carga do servidor e restaurar o desempenho ideal do Redis.
Por que o Redis está usando alta CPU? Técnicas de depuração e otimização
Alta CPU no Redis geralmente significa uma de três coisas: o Redis está fazendo muito trabalho de comando em seu caminho de execução principal, o trabalho em segundo plano, como persistência, está adicionando pressão, ou os clientes estão enviando tráfego em um formato que o Redis não consegue processar de forma eficiente. A correção depende de qual delas é verdadeira.
Não comece reiniciando o Redis, a menos que o serviço já esteja falhando. Uma reinicialização pode limpar o sintoma e apagar as evidências. Comece capturando a latência dos comandos, a mistura de comandos, o número de clientes, o estado da persistência e a CPU do host. Esses fatos informam se você tem um comando ruim, um padrão de tráfego ruim, um único núcleo sobrecarregado ou um host ruidoso.
Entendendo a Arquitetura do Redis e a Carga da CPU
O Redis é frequentemente descrito como single-threaded, o que é principalmente verdade para a execução de comandos, mas o Redis moderno também pode usar threads em segundo plano e I/O threading opcional. O ponto prático ainda é o mesmo: um comando que leva muito tempo pode atrasar outros clientes, e um núcleo saturado pode ser suficiente para criar latência visível, mesmo quando a máquina tem CPU ociosa em outro lugar.
Fatores Chave que Influenciam a Carga da CPU no Redis
Causas comuns são comandos caros, valores grandes, scripts Lua, muitos comandos pequenos enviados um round trip de cada vez, alta rotatividade de conexões, atividade de persistência e pressão de memória que força o kernel a trabalhar mais do que o Redis espera.
Depurando o Alto Uso de CPU
Antes de otimizar, você deve identificar com precisão a origem da carga. Ferramentas de monitoramento e comandos internos do Redis são essenciais para o diagnóstico.
1. Usando os Comandos INFO e LATENCY
O comando INFO fornece um instantâneo do status do servidor. Concentre-se na seção de CPU e nas estatísticas de comando.
redis-cli INFO cpu
Observe a taxa de mudança, não apenas os valores absolutos. used_cpu_user aumentando rapidamente geralmente aponta para processamento de comandos. used_cpu_sys aumentando rapidamente pode apontar para trabalho do kernel, como rede, gerenciamento de memória ou atividade relacionada a disco.
As ferramentas de latência mostram as classes de eventos que o Redis observou:
redis-cli LATENCY LATEST
redis-cli LATENCY DOCTOR
2. Identificando Comandos Lentos com SLOWLOG
O Slow Log do Redis registra comandos que excedem um tempo de execução especificado. Esta é sua ferramenta mais direta para encontrar operações com baixo desempenho.
O slow log do Redis registra comandos cujo tempo de execução excede um limite. Ele não inclui o tempo de rede ou o tempo de espera no pool de clientes, por isso é melhor usado junto com métricas de latência da aplicação.
Exemplo de Configuração:
slowlog-log-slower-than 1000
slowlog-max-len 1024
Recuperando o Log:
redis-cli SLOWLOG GET 10
Revise o nome do comando, nomes das chaves e duração. Se KEYS, HGETALL grande, SMEMBERS enorme, intervalos amplos de conjuntos ordenados ou scripts Lua dominarem o log, o problema de CPU é provavelmente orientado pela aplicação.
3. Monitorando a Atividade de Rede e Clientes
MONITOR é tentador durante um incidente, mas é caro em um servidor ocupado. Prefira INFO commandstats, INFO clients, slow log, métricas da biblioteca do cliente e amostragem de uma réplica, se você tiver uma.
Comandos úteis:
redis-cli INFO commandstats
redis-cli INFO clients
redis-cli CLIENT LIST
Se o volume de comandos dobrou após uma implantação, você pode ver isso em cmdstat_get, cmdstat_hgetall ou contadores semelhantes. Se os clientes estão constantemente conectando e desconectando, corrija o pooling antes de ajustar o Redis.
Causas Comuns e Estratégias de Otimização
Depois de identificar comandos ou processos problemáticos, aplique técnicas de otimização direcionadas.
1. Eliminando Comandos Bloqueantes
As vitórias mais rápidas geralmente vêm da remoção de comandos que forçam o Redis a percorrer um enorme espaço de chaves ou serializar um valor enorme.
| Comando Ineficiente | Por que causa alta CPU | Otimização / Alternativa |
|---|---|---|
KEYS * |
Varre todo o espaço de chaves. O(N). | Use SCAN iterativamente ou reestruture o acesso aos dados. |
FLUSHALL / FLUSHDB |
Exclui todas as chaves, a menos que o modo assíncrono seja usado. | Use exclusão cuidadosa com escopo, UNLINK ou limpeza assíncrona apenas quando apropriado. |
HGETALL, SMEMBERS (em conjuntos muito grandes) |
Recupera toda a estrutura para a memória e a serializa. | Use HSCAN, SSCAN ou divida estruturas grandes em chaves menores. |
Use UNLINK em vez de DEL para chaves muito grandes. DEL libera memória de forma síncrona. UNLINK remove a chave do espaço de chaves e libera memória de forma assíncrona, o que geralmente reduz a latência visível durante grandes exclusões.
# Em vez de DEL large_key
UNLINK large_key
2. Otimizando a Persistência (RDB e AOF)
Snapshots RDB e reescritas AOF usam processos filhos em segundo plano e ainda podem afetar o processo pai através do custo do fork, copy-on-write de memória, largura de banda de disco e contenção de CPU.
- Snapshots RDB: Se você está salvando com frequência (por exemplo, a cada minuto), as chamadas repetidas
fork()causarão picos recorrentes de CPU. Reduza a frequência dos salvamentos automáticos. - Reescrita AOF: A reescrita AOF (
BGREWRITEAOF) também consome muitos recursos. O Redis tenta otimizar isso realizando I/O mínimo, mas o uso da CPU aumentará durante o processo.
Se a persistência coincidir com picos de CPU, verifique INFO persistence e métricas de disco do host. Você pode reduzir a frequência do RDB, agendar backups pesados longe dos picos de tráfego, deixar mais espaço livre de memória ou melhorar o armazenamento. Pausar a persistência pode reduzir a carga, mas também aumenta o risco de perda de dados, portanto, deve ser uma decisão operacional deliberada.
3. Lidando com Fragmentação de Memória e Swapping
Embora os problemas de memória sejam frequentemente associados ao alto uso de memória, fragmentação severa de memória ou, pior, o sistema operacional começando a trocar dados do Redis para o disco (thrashing) aumentará drasticamente o uso da CPU, pois o kernel luta para gerenciar a memória.
- Verifique Swapping: Use ferramentas do SO (
vmstat,top) para verificar se o sistema está trocando ativamente páginas de memória pertencentes ao processo Redis. - Taxa de Fragmentação de Memória: Verifique
mem_fragmentation_ratioemINFO memory. Uma taxa alta é uma pista de que o comportamento do alocador pode estar desperdiçando memória, mas confirme com RSS, tamanho do conjunto de dados e métricas de memória do host.
Se ocorrer swapping, reduza o conjunto de dados, diminua maxmemory, mova o trabalho para fora do host ou adicione memória. O Redis não foi projetado para ter um bom desempenho quando seu conjunto de dados ativo está sendo paginado para o disco.
4. Otimização de Rede e Pipelining
Se a carga da CPU acompanhar um grande número de comandos pequenos, o problema pode ser a sobrecarga de comandos e a rotatividade de rede, em vez de um comando obviamente lento.
O pipelining permite que um cliente envie vários comandos sem esperar por uma resposta após cada um. Ele reduz as viagens de ida e volta e pode melhorar a taxa de transferência para gravações ou leituras em massa. Mantenha os lotes de pipeline limitados; um pipeline com milhares de comandos pesados pode criar seu próprio pico de latência.
Melhores Práticas para Desempenho Sustentado
Para evitar futuros picos de CPU, adote estas melhores práticas arquiteturais e de configuração:
- Use
UNLINKpara chaves que podem ser grandes. - Substitua
KEYSporSCANe substitua leituras completas de coleções por leituras baseadas em cursor. - Acompanhe
INFO commandstatsapós as implantações para que um novo padrão de comando não o surpreenda. - Ajuste a persistência com base no espaço livre real de disco e memória.
- Se uma instância do Redis estiver legitimamente saturada após correções de comandos, divida a carga de trabalho com Redis Cluster, sharding no lado do cliente, instâncias separadas de cache/sessão ou uma instância maior com melhor desempenho de núcleo único.
Uma lista de verificação rápida para incidentes
Durante um pico, execute:
redis-cli INFO cpu
redis-cli INFO commandstats
redis-cli INFO clients
redis-cli INFO memory
redis-cli INFO persistence
redis-cli SLOWLOG GET 20
redis-cli LATENCY LATEST
Em seguida, alinhe esses resultados com implantações de aplicativos, jobs cron, mudanças de tráfego, eventos de persistência e métricas do host. Alta CPU no Redis geralmente é corrigível, mas a correção é específica: remova o comando caro, agrupe o cliente tagarela, pare a rotatividade de conexões, dê espaço para a persistência funcionar ou divida a carga de trabalho quando uma única instância estiver genuinamente no seu limite.