...

Agendador de E/S Linux: Noop, mq-deadline e BFQ explicados na hospedagem

O I/O Scheduler Linux decide como o sistema classifica, prioriza e envia acessos de leitura e gravação para SSD, NVMe e HDD. Neste guia, explico de forma prática quando Noop, prazo mq e BFQ são a melhor escolha em termos de alojamento – incluindo afinação, testes e etapas de ação claras.

Pontos centrais

  • Noop: Overhead mínimo em SSD/NVMe e em VMs
  • prazo mq: Latência e taxa de transferência equilibradas para servidores
  • BFQ: Equidade e resposta rápida em ambientes multiusuário
  • blk-mq: Design multi-fila para hardware moderno
  • Afinação: Testes por carga de trabalho em vez de regras fixas

Como funciona o I/O Scheduler na hospedagem Linux

Um programador de E/S do Linux organiza as solicitações de E/S em filas, realiza a fusão e decide a entrega ao dispositivo para Latência e aumentar o rendimento. Os kernels modernos utilizam blk-mq, ou seja, multi-queue, para que vários núcleos de CPU possam iniciar I/O em paralelo. Isso é adequado para SSDs NVMe, que oferecem muitas filas e alta paralelidade, reduzindo assim as filas de espera. Na hospedagem, muitas vezes ocorrem cargas mistas amplas: servidores web fornecem muitas pequenas leituras, bancos de dados geram gravações sincronizadas e backups geram fluxos. O agendador adequado reduz congestionamentos, mantém os tempos de resposta estáveis e protege o Servidor-Experiência sob carga.

blk-mq na prática: none vs. noop e predefinições do kernel

Desde o kernel 5.x, o design multi-fila é o caminho padrão. Nesse caso, nenhum o equivalente „Noop“ para blk-mq, enquanto noop historicamente proveniente do caminho de fila única. Em dispositivos NVMe, geralmente apenas nenhum disponível; em SATA/SAS, é comum ver prazo mq, opcional bfq e, dependendo da distribuição, também kyber. Os padrões variam: o NVMe geralmente inicia com nenhum, SCSI/SATA frequentemente com prazo mq. Por isso, verifico sempre as opções disponíveis através de cat /sys/block//queue/scheduler e decida por dispositivo. Onde apenas nenhum é selecionável, isso é intencional – uma classificação adicional não traz praticamente nenhum valor acrescentado.

Noop em utilização no servidor: quando o minimalismo ganha

O Noop realiza principalmente a fusão de blocos adjacentes, mas não os ordena, o que torna a sobrecarga da CPU extremamente baixo mantém. Em SSDs e NVMe, os controladores e o firmware assumem a sequência inteligente, de modo que a classificação adicional no kernel dificilmente traz benefícios. Em VMs e contentores, costumo planear o Noop, porque o hipervisor faz o planeamento de forma abrangente. Em discos rotativos, dispenso o Noop, pois a falta de ordenação aumenta os tempos de busca. Quem quiser delimitar com segurança o contexto do hardware deve primeiro verificar o tipo de memória – aqui, é útil dar uma olhada em NVMe, SSD e HDD, antes de eu usar o Scheduler determinar.

mq-deadline: prazos, sequências e prioridades claras

O mq-deadline atribui prazos curtos aos acessos de leitura e faz com que os acessos de escrita esperem um pouco mais, a fim de Tempo de resposta O Scheduler também classifica por endereços de bloco, reduzindo assim os tempos de pesquisa, o que ajuda principalmente os HDDs e os conjuntos RAID. Em hosts web e de bases de dados, o mq-deadline oferece um bom equilíbrio entre latência e rendimento. Gosto de usá-lo quando as cargas de trabalho são mistas e há leituras e gravações em espera de forma contínua. Para o ajuste fino, verifico a profundidade da solicitação, o comportamento de writeback e o cache do controlador para garantir que a lógica do prazo seja consistente. agarra.

BFQ: Equidade e capacidade de resposta para muitos utilizadores simultâneos

O BFQ distribui a largura de banda proporcionalmente e atribui orçamentos por processo, o que é notável. justo funciona quando muitos utilizadores geram E/S em paralelo. Tarefas interativas, como shells de administração, editores ou chamadas de API, permanecem rápidas, mesmo com backups a decorrer em segundo plano. Em HDDs, o BFQ frequentemente atinge alta eficiência, pois aproveita fases sequenciais e usa janelas de inatividade curtas de maneira inteligente. Em SSDs muito rápidos, há um pequeno esforço adicional, que eu comparo com a resposta perceptível. Quem usa Cgroups e ioprio pode criar garantias claras com o BFQ e, assim, evitar aborrecimentos com vizinhos barulhentos. Evitar.

QoS no dia a dia: ioprio, ionice e Cgroups v2 com BFQ

Para limpar Definição de prioridades Eu combino BFQ com regras de processo e cgroup. No nível do processo, eu defino com ionice Classes e prioridades: ionice -c1 (em tempo real) para leituras críticas em termos de latência, ionice -c2 -n7 (Melhor esforço, baixo) para backups ou execuções de índice, ionice -c3 (Idle) para tudo o que deve funcionar apenas em períodos de inatividade. No Cgroups v2, utilizo io.weight para proporções relativas (por exemplo, 100 vs. 1000) e io.max para limites rígidos, por exemplo echo "259:0 rbps=50M wbps=20M" > /sys/fs/cgroup//io.max. Com o BFQ, os pesos são convertidos com grande precisão em proporções de largura de banda – ideal para alojamento partilhado e hosts de contentores, nos quais Equidade é mais importante do que a potência bruta máxima.

Comparação prática: qual escolha de hardware é adequada

A escolha depende muito do tipo de memória e da arquitetura da fila, por isso, primeiro verifico Dispositivo e controladores. SSD e NVMe beneficiam-se principalmente do Noop/none, enquanto HDDs funcionam melhor com mq-deadline ou BFQ. Em configurações RAID, SANs e hosts versáteis, prefiro frequentemente o mq-deadline, porque a lógica do Deadline e a classificação harmonizam-se bem. Ambientes multiusuário com muitas sessões interativas geralmente se beneficiam do BFQ. A tabela a seguir resume os pontos fortes e os campos de aplicação úteis de forma clara juntos:

agendador Hardware Pontos fortes Pontos fracos Cenários de alojamento
Noop/nenhum SSD, NVMe, VMs Overhead mínimo, fusão limpa Sem classificação em discos rígidos, desvantajoso Servidor Flash, contentor, controlado por hipervisor
prazo mq HDD, RAID, servidor multifuncional Prioridade de leitura rigorosa, ordenação, latência sólida Mais lógica do que Noop Bases de dados, back-ends web, cargas mistas
BFQ HDD, multiutilizadores, anfitriões semelhantes a computadores de secretária Justiça, capacidade de reação, boas sequências Um pouco mais de sobrecarga em SSDs muito rápidos Serviços interativos, alojamento partilhado, servidor de desenvolvimento

Configuração: verificar o agendador e definir como permanente

Primeiro, vejo qual agendador está ativo, por exemplo, com cat /sys/block/sdX/queue/scheduler, e anote o Opção entre parênteses retos. Para mudar temporariamente, escrevo, por exemplo echo mq-deadline | sudo tee /sys/block/sdX/queue/scheduler. Para configurações persistentes, utilizo regras udev ou parâmetros do kernel, como scsi_mod.use_blk_mq=1 e prazo mq na linha de comando. Para dispositivos NVMe, verifico os caminhos em /sys/block/nvme0n1/queue/ e defina a seleção por dispositivo. Importante: eu documento as alterações para que a manutenção e a reversão possam ser feitas sem suposições. ter sucesso.

Persistência e automatização na operação

No dia a dia, eu priorizo a repetibilidade em detrimento da automatização. Três métodos têm se mostrado eficazes:

  • Regras udev: Exemplo para todos os discos rígidos (rotacional=1) echo 'ACTION=="add|change", KERNEL=="sd*", ATTR{queue/rotational}=="1", ATTR{queue/scheduler}="mq-deadline"' > /etc/udev/rules.d/60-io-scheduler.rules, então udevadm control --reload-rules && udevadm trigger.
  • systemd-tmpfiles: Para dispositivos específicos, defino /etc/tmpfiles.d/blk.conf com frases como w /sys/block/sdX/queue/scheduler - - - - mq-deadline, que escrevem durante o arranque.
  • Gestão de configuração: No Ansible/Salt, crio classes de dispositivos (NVMe, HDD) e distribuo predefinições consistentes, incluindo documentação e reversão.

Nota: elevador= como parâmetro do kernel era válido para o antigo caminho de fila única. No blk-mq, eu determino a escolha por aparelho. Para stacks (dm-crypt, LVM, MD), defino a configuração padrão no dispositivo superior. Mais informações sobre isso abaixo.

Cargas de trabalho na hospedagem: reconhecer padrões e agir corretamente

Primeiro, analiso a carga: muitas pequenas leituras indicam interfaces web, gravações pesadas de sincronização em bases de dados e pipelines de registo, grandes fluxos sequenciais em backups ou Arquivo. Ferramentas como iostat, vmstat e blktrace mostram filas de espera, latências e efeitos de fusão. Em caso de tempo de inatividade da CPU perceptível devido a E/S, remeto para Entender a espera de E/S, para resolver os pontos críticos de forma estruturada. Depois, testo 1–2 candidatos a programadores em intervalos de tempo idênticos. São os resultados das medições que decidem, não a intuição ou mitos.

Aprofundar a prática de medição: benchmarks reprodutíveis

Para tomar decisões sólidas, utilizo métodos controlados fioPerfis e confirmação com testes reais da aplicação:

  • Leituras aleatórias (Web/Cache): fio --name=rr --rw=randread --bs=4k --iodepth=32 --numjobs=4 --runtime=120 --time_based --filename=/mnt/testfile --direct=1
  • Mistura aleatória (DB): fio --name=randmix --rw=randrw --rwmixread=70 --bs=8k --iodepth=64 --numjobs=8 --runtime=180 --time_based --direct=1
  • Sequencialmente (Cópia de segurança): fio --name=seqw --rw=write --bs=1m --iodepth=128 --numjobs=2 --runtime=120 --time_based --direct=1

Paralelamente, eu faço login iostat -x 1, pidstat -d 1 e anote as latências P95/P99 fio. Para diagnósticos aprofundados, utilizo blktrace ou ferramentas eBPF, como biolaticência Importante: eu faço as medições nos mesmos horários do dia, com as mesmas janelas de carga e os mesmos tamanhos de ficheiro. Eu minimizo os efeitos do cache com direct=1 e pré-condições limpas (por exemplo, pré-preenchimento no volume).

Sistemas de ficheiros e programador de E/S: a interação é importante

O sistema de ficheiros influencia as características de E/S, por isso verifico cuidadosamente o seu modo de registo, profundidade da fila e comportamento de sincronização. exatamente. EXT4 e XFS funcionam eficientemente com mq-deadline, enquanto ZFS armazena e agrega muitas coisas por conta própria. Em hosts com ZFS, observo que o efeito do agendador é frequentemente menor, porque o ZFS já molda a saída. Para comparações, utilizo opções de montagem e cargas de trabalho idênticas. Quem estiver a ponderar opções, encontrará em EXT4, XFS ou ZFS perspetivas úteis sobre Armazenamento-Afinação.

Writeback, cache e barreiras: a metade frequentemente ignorada

Os agendadores só podem funcionar tão bem quanto o subsistema de registo permite. Por isso, verifico sempre:

  • parâmetro sujo: sysctl vm.dirty_background_bytes, vm.dirty_bytes, vm.dirty_expire_centisecs controlar quando e com que agressividade o kernel grava. Para bases de dados, muitas vezes reduzo os picos de burst para manter o P99 estável.
  • Barreiras/Flush: Opções como EXT4 barreira ou XFS Default-Flushes, eu só os protejo se o hardware (por exemplo, BBWC) os assumir. „nobarrier“ sem proteção contra energia é arriscado.
  • Cache de escrita do dispositivo: Verifico as configurações da cache de escrita do controlador para que fsync realmente chega ao meio de armazenamento e não apenas à cache.

Quem suaviza o Writeback alivia o Scheduler – os prazos permanecem fiáveis e o BFQ tem menos trabalho para lidar com ondas repentinas de flush.

Virtualização, contentores e nuvem: quem está realmente a planear?

Nas VMs, o hipervisor controla o fluxo físico de E/S, por isso, muitas vezes, seleciono Noop/none no convidado para evitar duplicação. Lógica evitar. No próprio host, utilizo mq-deadline ou BFQ, dependendo do dispositivo e da tarefa. No caso de volumes na nuvem (por exemplo, armazenamento em bloco de rede), parte do planeamento fica no backend; por isso, meço latências reais em vez de confiar em suposições. Para hosts de contentores com carga muito mista, o BFQ frequentemente oferece melhor interatividade. Em clusters de lotes homogéneos com apenas flash, o Noop prevalece porque cada tempo de CPU conta e os controladores são eficientes. trabalho.

RAID, LVM, MD e Multipath: onde o Scheduler intervém

Em pilhas de blocos empilhados, coloco o programador no Dispositivo de topo , pois é aí que se encontram as filas relevantes:

  • LVM/dm-crypt: Agendador em /dev/dm-* respectivamente /dev/mapper/ colocar. Normalmente, deixo os PVs físicos em nenhum, para que a fusão/classificação não ocorra duas vezes.
  • MD-RAID: No /dev/mdX decidir; abaixo sdX Os dispositivos permanecem tranquilos nenhum. O RAID de hardware é tratado como um único dispositivo de bloco.
  • Multicaminho: No Multipath-Mapper (/dev/mapper/mpatha); defina os dispositivos de caminho abaixo em nenhum.

Importante: Eu separo os testes por piscina e nível de redundância (RAID1/10 vs. RAID5/6). Os RAIDs de paridade são mais sensíveis a gravações aleatórias; aqui, o mq-deadline costuma ganhar devido aos prazos de leitura consistentes e à saída ordenada.

Estratégias de afinação: passo a passo para um desempenho fiável

Começo com uma medição básica: tempos de resposta atuais, taxa de transferência, percentis 95/99 e CPU.Carga. Depois disso, altero apenas um fator, normalmente o agendador, e repito a mesma carga. Ferramentas como fio ajudam a controlar, mas eu confirmo cada hipótese com testes de aplicação reais. Para bases de dados, são adequados benchmarks próprios que reproduzem transações e comportamento fsync. Só quando a medição está estável é que eu defino a escolha e documento o Porquê.

Profundidade da fila, leitura antecipada e afinidade da CPU

Além do agendador, os parâmetros da fila têm grande influência na prática:

  • Profundidade da fila: /sys/block//queue/nr_requests Limita as solicitações pendentes por fila de hardware. O NVMe suporta alta profundidade (alto rendimento), enquanto os HDDs beneficiam de profundidade moderada (latência mais estável).
  • Readahead: /sys/block//queue/read_ahead_kb respectivamente blockdev --getra/setra. Para cargas de trabalho sequenciais, mantenha um valor ligeiramente mais alto; para cargas de trabalho aleatórias, mantenha um valor baixo.
  • rq_affinityCom /sys/block//queue/rq_affinity No ponto 2, garanto que a conclusão da E/S seja direcionada preferencialmente para o núcleo da CPU que a gerou, o que reduz os custos entre CPUs.
  • rotacional: Confirmo que os SSDs rotacional=0 para que o kernel não aplique heurísticas HDD.
  • Mesclagens: /sys/block//queue/nomerges Pode reduzir as fusões (2=desativado). Útil para NVMe com microlatência, mas geralmente prejudicial para HDDs.
  • io_poll (NVMe): O polling pode reduzir as latências, mas requer CPU. Eu ativo-o especificamente em Baixa latência-Requisitos.

Scheduler-Tunables em detalhe

Dependendo do programador, existem ajustes precisos úteis disponíveis:

  • prazo mq: /sys/block//queue/iosched/read_expire (ms, tipicamente pequeno), write_expire (maior), fifo_batch (tamanho do lote), front_merges (0/1). Eu considero read_expire brevemente, para proteger as leituras P95, e ajuste fifo_batch dependendo do dispositivo.
  • BFQ: slice_idle (Tempo ocioso para utilização da sequência), baixa latência (0/1) para interatividade responsiva. Com bfq.weight Nos Cgroups, controlo as quotas relativas com muita precisão.
  • nenhum/noop: Quase sem parafusos de ajuste, mas a Arredores (profundidade da fila, leitura antecipada) determina os resultados.

Eu altero sempre apenas um parâmetro e registo rigorosamente a alteração – assim fica claro qual foi o efeito de cada alteração.

Armadilhas comuns e como as evito

Pools mistos de HDD e SSD atrás de um controlador RAID distorcem os testes, por isso separo as medições por Grupo. Não me esqueço que o agendador se aplica por dispositivo de bloco – considero o LVM-Mapper e os dispositivos MD separadamente. A persistência tende a escapar: sem a regra udev ou o parâmetro do kernel, após a reinicialização, volta-se ao padrão. Cgroups e prioridades de E/S muitas vezes permanecem inutilizadas, embora aumentem significativamente a equidade. E eu sempre verifico a profundidade da fila, o writeback e as opções do sistema de ficheiros para que a lógica escolhida alcance o seu potencial. espectáculos.

Resolução de problemas: ler os sintomas de forma específica

Quando os valores medidos mudam, eu interpreto os padrões e deduzo medidas concretas:

  • Alta latência P99 em muitas leituras: Verificar se as gravações substituem as leituras. Testar com mq-deadline., read_expire reduzir, suavizar a reversão (vm.dirty_* ajustar).
  • 100% util no HDD, baixo rendimento: Dominar as pesquisas. Experimentar BFQ ou mq-deadline, reduzir o readahead, moderar a profundidade da fila.
  • Bons valores de rendimento, mas a interface do utilizador é instável: A interatividade é prejudicada. Ativar BFQ, serviços críticos por ionice -c1 ou pesos Cgroup.
  • Grande variação dependendo da hora do dia: Recursos partilhados. Isolar com Cgroups, selecionar o programador por pool, transferir as cópias de segurança para fora do horário de pico.
  • Timeouts NVMe no dmesg: Questão relacionada com o backend ou firmware. io_poll Desativar para teste, verificar firmware/driver, verificar redundância de caminho (multicaminho).

Resumo: decisões claras para o dia a dia da hospedagem

Para armazenamento flash e convidados, muitas vezes opto por Noop, para economizar despesas gerais e deixar os controladores a trabalhar. Em servidores versáteis com HDD ou RAID, o mq-deadline oferece latência confiável e alta usabilidade. Com muitos utilizadores ativos e carga interativa, o BFQ garante distribuições justas e respostas rápidas. Antes de cada gravação, faço medições com cargas de trabalho reais e observo os efeitos em P95/P99. Assim, tomo decisões compreensíveis, mantenho os sistemas rápidos e estabilizo o Servidor-Desempenho nas atividades diárias.

Artigos actuais