Dissecando a latência de I/O: por que médias mentem e histogramas salvam o dia

      Rafael Junqueira 11 min de leitura
      Dissecando a latência de I/O: por que médias mentem e histogramas salvam o dia

      Aprenda a investigar gargalos de armazenamento no Linux usando eBPF. Descubra por que ferramentas como iostat falham em detectar latência de cauda e como usar histogramas para garantir seus SLOs.

      Compartilhar:

      Às 03:14 da manhã, o pager toca. O alerta indica que o serviço de banco de dados principal está queimando o orçamento de erro (error budget) a uma taxa alarmante. Latência de transação inaceitável. Você abre o dashboard do Grafana, com os olhos semicerrados, e olha para o gráfico de latência média de disco (avg_lat). A linha está plana, calma, repousando confortavelmente em 2ms. O sistema diz que está tudo bem. Os clientes dizem que o sistema está quebrado.

      Neste momento, você está sendo vítima da mentira mais perigosa da observabilidade de armazenamento: a média aritmética.

      Em sistemas distribuídos e infraestruturas de armazenamento de alta performance, a média apaga os crimes do sistema. Ela esconde o "long tail" (a cauda longa), aqueles 1% ou 0,1% de requisições que levam 500ms ou 1 segundo para completar, travando threads de aplicação e causando timeouts em cascata. Como Engenheiros de Confiabilidade (SREs), nosso trabalho não é olhar para o comportamento "normal", mas sim obsessivamente para os outliers que violam nossos Objetivos de Nível de Serviço (SLOs).

      Resumo em 30 segundos

      • Médias são vaidade, percentis são sanidade: A latência média esconde picos transientes que destroem a experiência do usuário; monitore sempre p99 e p99.9.
      • O iostat é insuficiente para NVMe: Ferramentas baseadas em amostragem de segundos perdem micro-picos de latência em dispositivos que operam na casa dos microssegundos.
      • Histogramas via eBPF são a verdade: A única forma de visualizar a distribuição real de I/O e identificar gargalos no kernel ou no firmware do disco é através de instrumentação de alta fidelidade.

      O alerta de latência de cauda e a invisibilidade no monitoramento padrão

      Quando definimos um Indicador de Nível de Serviço (SLI) para armazenamento, frequentemente caímos na armadilha de usar métricas padrão fornecidas pelo sistema operacional. Um disco rígido (HDD) ou um SSD Enterprise não responde de forma linear. A latência de I/O raramente segue uma distribuição normal (curva de sino). Ela é multimodal.

      Imagine um array de armazenamento ZFS ou um cluster Ceph. A maioria das leituras pode vir do cache ARC ou da RAM (latência de microssegundos). Outras vêm do flash NAND (latência de ~100us). E algumas, as infelizes, precisam buscar dados em discos rotacionais que estavam em spin-down ou aguardando uma operação de seek mecânico (latência de >10ms).

      Se você tem 1.000 requisições a 0,1ms e 5 requisições a 200ms, sua média será aproximadamente 1ms. O dashboard mostra "1ms - Excelente". Mas para os 5 usuários que caíram naquelas requisições de 200ms (ou para o banco de dados que travou esperando o commit do log), o sistema parou.

      Fig. 1: A ilusão da média aritmética vs. a realidade da distribuição multimodal em latência de disco. Fig. 1: A ilusão da média aritmética vs. a realidade da distribuição multimodal em latência de disco.

      ⚠️ Perigo: Ignorar a latência de cauda (p99 ou p99.9) em discos NVMe é fatal. Um SSD moderno pode processar 500.000 IOPS. Um pico de latência de 50ms, invisível na média, pode significar o bloqueio de milhares de operações subsequentes na fila do kernel.

      A cultura de SRE exige que paremos de culpar "o disco lento" e comecemos a investigar a distribuição de probabilidade dessas latências. Se o seu SLO diz que "99% das leituras devem ocorrer em menos de 10ms", a média é matematicamente irrelevante para provar conformidade.

      A jornada do bloco: entendendo a pilha de armazenamento do Linux

      Para diagnosticar latência, precisamos dissecar onde o tempo é gasto. O conceito de "latência de disco" é frequentemente um termo guarda-chuva impreciso. Quando uma aplicação emite uma syscall de leitura (read()), o relógio começa a contar, mas o "disco" físico é apenas o destino final de uma longa jornada burocrática.

      1. VFS (Virtual File System): A camada de abstração. Aqui, o custo é geralmente CPU e acesso a metadados em RAM.

      2. Page Cache: Se o dado estiver aqui, o I/O nem toca o disco. Latência de nanosegundos.

      3. Camada de Bloco (Block Layer): Aqui as bios (block I/O structures) são formadas. É onde a mágica e o caos acontecem.

      4. Escalonador de I/O (Scheduler): BFQ, Kyber, MQ-Deadline. O kernel pode decidir segurar sua requisição para fundi-la com outra (merge) ou reordená-la para eficiência. Latência de fila (Queue Latency) é introduzida aqui.

      5. Driver (NVMe/SCSI): A entrega para o hardware.

      6. Dispositivo Físico: O tempo que o controlador do SSD leva para programar as células NAND ou o braço do HDD leva para se mover.

      Muitas vezes, o que chamamos de "latência de disco" é, na verdade, "latência de escalonamento do kernel". Em ambientes virtualizados ou containers (Kubernetes), a contenção de CPU (CPU Throttling) pode fazer com que o envio da requisição ao disco demore. O disco é rápido, mas o kernel demorou para despachar o pedido.

      💡 Dica Pro: Em servidores de banco de dados dedicados com NVMe, verifique se o escalonador de I/O está definido como none ou kyber. Escalonadores complexos como BFQ adicionam overhead de CPU desnecessário para dispositivos que não têm penalidade de busca mecânica.

      As limitações do iostat na detecção de micro-picos em NVMe

      A ferramenta iostat (do pacote sysstat) é o estetoscópio do engenheiro de sistemas há décadas. No entanto, em uma era de dispositivos NVMe Gen4 e Gen5 capazes de latências de 20 microssegundos, o iostat é como tentar medir a velocidade de uma bala com um cronômetro manual.

      O problema reside na resolução de amostragem. O comando padrão iostat -x 1 coleta estatísticas a cada segundo. Ele lê o arquivo /proc/diskstats, calcula a diferença desde a última leitura e divide pelo tempo.

      Se o seu SSD NVMe sofrer um "stutter" (engasgo) de 200ms devido a uma coleta de lixo (Garbage Collection) interna do firmware, mas passar os outros 800ms do segundo voando baixo, o iostat reportará uma utilização e latência médias moderadas. O pico desaparece na diluição temporal.

      Além disso, a métrica %util do iostat é notoriamente enganosa para armazenamento moderno. Ela mede a saturação do tempo, não a capacidade do dispositivo. Um disco com %util 100 pode estar apenas processando uma única requisição lenta sequencial, enquanto ainda teria largura de banda para aceitar outras 10.000 requisições paralelas. Para SREs focados em storage, confiar cegamente no iostat para análise de causa raiz (RCA) de incidentes de micro-latência é negligência técnica.

      Instrumentação cirúrgica com eBPF e análise de distribuição

      Para resolver a cegueira das médias, precisamos de histogramas. E para obter histogramas sem derrubar a performance do servidor de produção, usamos eBPF (Extended Berkeley Packet Filter).

      O eBPF permite executar programas seguros e isolados dentro do kernel do Linux, acoplados a eventos (kprobes, tracepoints). Podemos medir o tempo exato entre o início de uma requisição de bloco (blk_account_io_start) e sua conclusão (blk_account_io_done), e então armazenar esse delta em um bucket de histograma na memória do kernel, enviando apenas o resumo para o espaço do usuário. Isso é eficiência extrema.

      Ferramentas do pacote BCC (BPF Compiler Collection) ou bpftrace são essenciais aqui.

      O poder do biolatency

      Ao rodar biolatency -m, obtemos uma visualização da verdade:

           msecs               : count     distribution
               0 -> 1          : 1945      |************************************|
               2 -> 3          : 20        |                                    |
               4 -> 7          : 5         |                                    |
               8 -> 15         : 2         |                                    |
              16 -> 31         : 0         |                                    |
              32 -> 63         : 0         |                                    |
              64 -> 127        : 142       |**                                  |
      

      Observe a distribuição acima. A média seria baixa. Mas aquele segundo pico entre 64ms e 127ms (142 ocorrências) é a "arma do crime". Isso é uma distribuição bimodal. Sem um histograma, você jamais saberia que existe um grupo de requisições sofrendo latência severa.

      Fig. 2: Infraestrutura física de alta performance onde milissegundos de latência se traduzem em violações de SLO. Fig. 2: Infraestrutura física de alta performance onde milissegundos de latência se traduzem em violações de SLO.

      O detalhe do biosnoop

      Enquanto biolatency nos dá o panorama estatístico, o biosnoop nos dá a autópsia de cada I/O. Ele pode nos dizer qual processo (PID), qual comando e qual setor do disco causou a latência.

      Isso permite correlacionar latência de armazenamento com eventos de aplicação. Por exemplo, você pode descobrir que a latência dispara apenas quando o processo de backup (tar ou pg_dump) compete com o processo principal do banco de dados, saturando as filas do dispositivo.

      Confirmando a mitigação através de histogramas de latência

      Uma vez identificado que a latência de cauda é a culpada pela violação do SLO, a mitigação deve ser aplicada e, crucialmente, verificada. Em um cenário real de pós-mortem, a correção pode envolver:

      1. Over-provisioning do SSD: Aumentar a área reservada do disco para facilitar o trabalho do controlador na coleta de lixo, reduzindo picos de latência de escrita.

      2. Isolamento de I/O: Usar cgroups (blkio) para garantir que processos de manutenção não roubem IOPS do serviço crítico.

      3. Ajuste de Queue Depth: Reduzir a profundidade da fila na aplicação para evitar bufferbloat no nível do driver.

      A confirmação não vem quando o ticket é fechado, mas quando o histograma muda. O objetivo é "apertar" a distribuição, eliminando a cauda longa à direita.

      Se após a alteração de configuração, o histograma do biolatency mostrar que o bucket de "64ms -> 127ms" desapareceu e as operações se concentraram abaixo de 4ms, você tem prova matemática de resolução. Isso é engenharia de confiabilidade baseada em dados, não em palpites.

      O imperativo da observabilidade de alta fidelidade

      À medida que avançamos para interfaces como CXL (Compute Express Link) e armazenamento persistente em memória, a margem para erro diminui. Latências que antes eram ruído estatístico em HDDs agora são interrupções de serviço em ambientes NVMe.

      Para o SRE moderno focado em infraestrutura de dados, a média aritmética é uma relíquia de uma era mais lenta. A sobrevivência e a conformidade com SLOs rigorosos dependem da nossa capacidade de visualizar, entender e domar a distribuição completa da latência. Adote histogramas, aprenda eBPF e pare de deixar que os outliers ditem a confiabilidade do seu sistema.

      Perguntas Frequentes

      1. Por que não usar apenas o percentil 99 (p99) para tudo? Embora o p99 seja superior à média, ele ainda descarta 1% dos dados. Em sistemas de hiperescala, 1% pode representar milhares de usuários insatisfeitos. O ideal é monitorar múltiplos percentis (p50, p90, p99, p99.9) e usar mapas de calor (heatmaps) para visualização completa.

      2. O uso de ferramentas eBPF como biolatency impacta a performance do servidor? O impacto é insignificante para a maioria dos workloads de produção. O eBPF executa bytecode verificado no kernel e apenas atualiza contadores em mapas de memória, evitando o custo de troca de contexto (context switch) de ferramentas de trace antigas como strace ou tcpdump.

      3. Como a latência de cauda afeta arrays RAID ou ZFS? Em arrays redundantes, a latência de uma operação de escrita é frequentemente ditada pelo disco mais lento do grupo (especialmente em escritas síncronas). Um único SSD falhando ou realizando wear leveling pode causar picos de latência em todo o pool de armazenamento, tornando a análise individual de discos via histogramas ainda mais crítica.

      4. O que é "Noisy Neighbor" em contexto de storage? É quando outra máquina virtual ou container no mesmo host físico ou SAN consome recursos excessivos de I/O, saturando as filas do dispositivo ou do switch. Isso gera latência de cauda para sua aplicação, mesmo que ela esteja consumindo pouco. Histogramas ajudam a provar que a lentidão é externa (tempo de espera na fila vs. tempo de serviço).

      Referências & Leitura Complementar

      • Gregg, Brendan. BPF Performance Tools: Linux System and Application Observability. Addison-Wesley Professional, 2019. (A bíblia da instrumentação moderna).

      • NVM Express. NVM Express Base Specification, Revision 2.0. 2021. (Para entender as filas de submissão e conclusão em hardware NVMe).

      • Google SRE Team. Site Reliability Engineering: How Google Runs Production Systems. O'Reilly Media, 2016. (Capítulo 6: Monitoring Distributed Systems).

      • Cao, Y. et al. Reliability of SSDs in Large-Scale Enterprise Storage Deployments. FAST '20. (Análise real de falhas e latências em datacenters).

      #eBPF #Linux Storage #Latência de Disco #Observabilidade SRE #NVMe Performance #BCC Tools #Engenharia de Confiabilidade
      Rafael Junqueira
      Assinatura Técnica

      Rafael Junqueira

      Engenheiro de Confiabilidade (SRE)

      "Transformo caos em estabilidade via observabilidade. Defensor da cultura blameless e focado em SLIs e SLOs. Se algo falhou, revisamos o sistema, nunca a pessoa."