...

Programador de E/S Linux: Noop, mq-deadline y BFQ explicados en el alojamiento web

El programador de E/S de Linux decide cómo el sistema clasifica y prioriza los accesos de lectura y escritura a SSD, NVMe y HDD, y cómo los envía al dispositivo. En esta guía explico de forma práctica cuándo Noop, mq-fecha límite y BFQ son la mejor opción para el alojamiento, incluyendo ajustes, pruebas y pasos claros a seguir.

Puntos centrales

  • Noop: Sobrecarga mínima en SSD/NVMe y en máquinas virtuales.
  • mq-fecha límite: Latencia y rendimiento equilibrados para servidores
  • BFQ: Equidad y respuesta rápida en entornos multiusuario
  • blk-mq: Diseño multicolumna para hardware moderno
  • Sintonización: Pruebas por carga de trabajo en lugar de reglas fijas

Cómo funciona el programador de E/S en el alojamiento Linux

Un programador de E/S de Linux ordena las solicitudes de E/S en colas, realiza fusiones y decide la entrega al dispositivo para Latencia y aumentar el rendimiento. Los núcleos modernos utilizan blk-mq, es decir, multi-cola, para que varios núcleos de CPU puedan iniciar E/S en paralelo. Esto encaja con los SSD NVMe, que ofrecen muchas colas y un alto grado de paralelismo, lo que reduce las colas de espera. En el alojamiento, a menudo se producen cargas mixtas amplias: los servidores web proporcionan muchas lecturas pequeñas, las bases de datos generan escrituras sincronizadas y las copias de seguridad generan flujos. El programador adecuado reduce los atascos, mantiene estables los tiempos de respuesta y protege la Servidor-Experiencia bajo carga.

blk-mq en la práctica: none vs. noop y valores predeterminados del kernel

Desde el kernel 5.x, el diseño multicoloca es la ruta estándar. En este caso, ninguno el equivalente „Noop“ para blk-mq, mientras que noop proviene históricamente de la ruta de cola única. En los dispositivos NVMe, normalmente solo ninguno disponible; en SATA/SAS se ve a menudo mq-fecha límite, opcional bfq y, dependiendo de la distribución, también kyber. Los valores predeterminados varían: NVMe suele iniciarse con ninguno, SCSI/SATA a menudo con mq-fecha límite. Por lo tanto, siempre compruebo las opciones disponibles a través de cat /sys/block//queue/scheduler y decide por dispositivo. ¿Dónde solo? ninguno es seleccionable, es intencionado: una clasificación adicional no aporta prácticamente ningún valor añadido.

Noop en el uso de servidores: cuándo gana el minimalismo

Noop realiza principalmente la fusión de bloques adyacentes, pero no los ordena, lo que reduce considerablemente la sobrecarga de la CPU. bajo En SSD y NVMe, los controladores y el firmware se encargan de la secuencia inteligente, por lo que la clasificación adicional en el núcleo apenas aporta beneficios. En máquinas virtuales y contenedores, suelo planificar Noop, ya que el hipervisor planifica de todos modos de forma global. En discos giratorios, prescindo de Noop, ya que la falta de clasificación aumenta los tiempos de búsqueda. Si se quiere delimitar con seguridad el contexto del hardware, hay que fijarse primero en el tipo de memoria; aquí es útil echar un vistazo a NVMe, SSD y HDD, antes de iniciar el programador establecer.

mq-deadline: plazos, secuencias y prioridades claras

mq-deadline establece plazos cortos para los accesos de lectura y hace que los accesos de escritura esperen un poco más para Tiempo de respuesta El programador también clasifica por direcciones de bloque, lo que reduce los tiempos de búsqueda, lo que resulta especialmente útil para los discos duros y las matrices RAID. En los hosts web y de bases de datos, mq-deadline ofrece un buen equilibrio entre latencia y rendimiento. Me gusta utilizarlo cuando las cargas de trabajo son mixtas y hay lecturas y escrituras pendientes de forma permanente. Para el ajuste fino, compruebo la profundidad de la solicitud, el comportamiento de reescritura y la caché del controlador para que la lógica de Deadline sea coherente. agarra.

BFQ: equidad y capacidad de respuesta para muchos usuarios simultáneos

BFQ distribuye el ancho de banda de forma proporcional y asigna presupuestos por proceso, lo que se nota. feria Funciona cuando muchos usuarios generan E/S en paralelo. Las tareas interactivas, como los shells de administración, los editores o las llamadas a la API, siguen funcionando con rapidez, aunque se estén realizando copias de seguridad en segundo plano. En los discos duros, BFQ suele alcanzar una alta eficiencia porque aprovecha las fases secuenciales y utiliza de forma inteligente las breves ventanas de inactividad. En los SSD muy rápidos se produce un pequeño esfuerzo adicional, que sopeso frente a la notable capacidad de respuesta. Quienes utilizan cgroups e ioprio pueden obtener garantías claras con BFQ y evitar así molestias por vecinos ruidosos. Evite.

QoS en el día a día: ioprio, ionice y Cgroups v2 con BFQ

Para limpiar Priorización Combino BFQ con reglas de proceso y cgroup. A nivel de proceso, utilizo ionice Clases y prioridades: ionice -c1 (tiempo real) para lecturas críticas en cuanto a latencia, ionice -c2 -n7 (mejor esfuerzo, bajo) para copias de seguridad o ejecuciones de índices, ionice -c3 (Idle) para todo lo que solo debe ejecutarse en tiempos de inactividad. En Cgroups v2 utilizo io.weight para proporciones relativas (por ejemplo, 100 frente a 1000) y io.max para límites estrictos, por ejemplo echo "259:0 rbps=50M wbps=20M" > /sys/fs/cgroup//io.max. Con BFQ, los pesos se convierten con gran precisión en proporciones de ancho de banda, lo que resulta ideal para el alojamiento compartido y los hosts de contenedores en los que Equidad es más importante que la potencia bruta máxima.

Comparación práctica: qué opción es la adecuada para el hardware

La elección depende en gran medida del tipo de memoria y de la arquitectura de la cola, por lo que primero compruebo Dispositivo y controladores. Los SSD y NVMe suelen beneficiarse de Noop/none, mientras que los HDD funcionan mejor con mq-deadline o BFQ. En configuraciones RAID, SAN y hosts versátiles, suelo preferir mq-deadline porque la lógica de deadline y la clasificación armonizan bien. Los entornos multiusuario con muchas sesiones interactivas suelen beneficiarse de BFQ. La siguiente tabla resume claramente las ventajas y los campos de aplicación más adecuados. juntos:

programador Hardware Puntos fuertes Puntos débiles Escenarios de alojamiento
Noop/ninguno SSD, NVMe, máquinas virtuales Sobrecarga mínima, fusión limpia Sin clasificación en discos duros, desfavorable Servidor Flash, contenedor, controlado por hipervisor
mq-fecha límite HDD, RAID, servidor versátil Prioridad de lectura estricta, clasificación, latencia sólida Más lógica que Noop Bases de datos, backends web, cargas mixtas
BFQ HDD, multiusuario, hosts similares a equipos de escritorio Equidad, capacidad de reacción, buenas secuencias. Un poco más de sobrecarga en SSD muy rápidos Servicios interactivos, alojamiento compartido, servidor de desarrollo

Configuración: comprobar el programador y establecerlo de forma permanente

Primero compruebo qué programador está activo, por ejemplo con cat /sys/block/sdX/queue/scheduler, y anota el Opción entre corchetes. Para cambiar temporalmente, escribo, por ejemplo echo mq-deadline | sudo tee /sys/block/sdX/queue/scheduler. Para configuraciones persistentes, utilizo reglas udev o parámetros del kernel como scsi_mod.use_blk_mq=1 y mq-fecha límite en la línea de comandos. En el caso de los dispositivos NVMe, compruebo las rutas en /sys/block/nvme0n1/queue/ y selecciona la opción para cada dispositivo. Importante: documento los cambios para que el mantenimiento y la reversión se puedan realizar sin conjeturas. triunfar.

Persistencia y automatización en el funcionamiento

En mi día a día, antepongo la repetibilidad a la automatización. Hay tres formas que han demostrado su eficacia:

  • Reglas udev: Ejemplo para todos los discos duros (rotacionales=1) echo 'ACTION=="add|change", KERNEL=="sd*", ATTR{queue/rotational}=="1", ATTR{queue/scheduler}="mq-deadline"' > /etc/udev/rules.d/60-io-scheduler.rules, entonces udevadm control --reload-rules && udevadm trigger.
  • systemd-tmpfiles: Para dispositivos específicos, defino /etc/tmpfiles.d/blk.conf con frases como w /sys/block/sdX/queue/scheduler - - - - mq-deadline, que escriben al arrancar.
  • Gestión de la configuración: En Ansible/Salt, creo clases de dispositivos (NVMe, HDD) y distribuyo valores predeterminados coherentes, junto con la documentación y la reversión.

Nota: elevador= como parámetro del núcleo se aplicaba a la antigua ruta de cola única. En blk-mq, yo determino la elección. por dispositivo. En el caso de las pilas (dm-crypt, LVM, MD), establezco el valor predeterminado en el dispositivo superior. Más información al respecto a continuación.

Cargas de trabajo en el alojamiento: reconocer patrones y actuar correctamente

Primero analizo la carga: muchas lecturas pequeñas indican interfaces web, escrituras con mucha sincronización en bases de datos y canalizaciones de registros, grandes flujos secuenciales en copias de seguridad o Archivo. Herramientas como iostat, vmstat y blktrace muestran colas, latencias y efectos de fusión. En caso de un tiempo de inactividad notable de la CPU debido a la E/S, remito a Entender la espera de E/S, para resolver los cuellos de botella de forma estructurada. A continuación, pruebo 1-2 candidatos a programador en intervalos de tiempo idénticos. Solo los resultados de las mediciones son decisivos, no la intuición o mitos.

Profundizar en la práctica de la medición: puntos de referencia reproducibles

Para tomar decisiones sólidas, utilizo fioPerfiles y confirmación mediante pruebas reales de la aplicación:

  • Lecturas aleatorias (Web/Caché): fio --name=rr --rw=randread --bs=4k --iodepth=32 --numjobs=4 --runtime=120 --time_based --filename=/mnt/testfile --direct=1
  • Mezcla aleatoria (DB): fio --name=randmix --rw=randrw --rwmixread=70 --bs=8k --iodepth=64 --numjobs=8 --runtime=180 --time_based --direct=1
  • Secuencial (Copia de seguridad): fio --name=seqw --rw=write --bs=1m --iodepth=128 --numjobs=2 --runtime=120 --time_based --direct=1

Al mismo tiempo, inicio sesión. iostat -x 1, pidstat -d 1 y anota las latencias P95/P99. fio. Para diagnósticos profundos utilizo blktrace o herramientas eBPF como biolatencia . Importante: realizo las mediciones a la misma hora del día, con las mismas ventanas de carga y los mismos tamaños de archivo. Minimizo los efectos de la caché con direct=1 y condiciones previas limpias (por ejemplo, prellenado en el volumen).

Sistemas de archivos y programadores de E/S: la interacción es importante

El sistema de archivos influye en las características de E/S, por lo que compruebo minuciosamente su modo de registro, la profundidad de la cola y el comportamiento de sincronización. exactamente. EXT4 y XFS funcionan de manera eficiente con mq-deadline, mientras que ZFS almacena y agrega gran parte por sí mismo. En hosts con ZFS, observo que el efecto del programador suele ser menor, ya que ZFS ya da forma a la salida. Para las comparaciones, utilizo opciones de montaje y cargas de trabajo idénticas. Si se están sopesando opciones, en EXT4, XFS o ZFS perspectivas útiles sobre Almacenamiento-Puesta a punto.

Writeback, caché y barreras: la mitad que a menudo se pasa por alto

Los programadores solo pueden funcionar tan bien como lo permita el subsistema de reescritura. Por lo tanto, siempre compruebo lo siguiente:

  • Parámetro dirty: sysctl vm.dirty_background_bytes, vm.bytes sucios, vm.dirty_expire_centisecs Controlar cuándo y con qué agresividad escribe el núcleo. Para las bases de datos, a menudo reduzco los picos de ráfagas para mantener estable el P99.
  • Barreras/Flush: Opciones como EXT4 barrera Solo aseguro los vaciados predeterminados de XFS si el hardware (por ejemplo, BBWC) los asume. „nobarrier“ sin protección contra descargas eléctricas es arriesgado.
  • Caché de escritura del dispositivo: Verifico la configuración de la caché de escritura del controlador para que fsync realmente llega al medio y no solo a la caché.

Quien suaviza Writeback alivia la carga del programador: los plazos siguen siendo fiables y BFQ tiene que trabajar menos contra las oleadas repentinas de vaciado.

Virtualización, contenedores y nube: ¿quién planifica realmente?

En las máquinas virtuales, el hipervisor controla el flujo físico de E/S, por lo que a menudo selecciono Noop/none en el invitado para evitar duplicados. lógica . En el propio host utilizo mq-deadline o BFQ, dependiendo del dispositivo y la tarea. En los volúmenes en la nube (por ejemplo, el almacenamiento en bloques de red), parte de la planificación se realiza en el backend, por lo que mido las latencias reales en lugar de basarme en suposiciones. Para los hosts de contenedores con una carga muy mixta, BFQ suele ofrecer una mejor interactividad. En clústeres por lotes homogéneos con solo flash, Noop se impone porque cada tiempo de CPU cuenta y los controladores son eficientes. trabajo.

RAID, LVM, MD y multipath: dónde interviene el programador

En pilas de bloques apilados, coloco el programador en el Dispositivo de gama alta , ya que allí se encuentran las colas relevantes:

  • LVM/dm-crypt: Programador en /dev/dm-* respectivamente /dev/mapper/ . Por lo general, dejo los PV físicos en ninguno, para que la fusión/clasificación no se realice dos veces.
  • MD-RAID: En /dev/mdX decidir; subyacente sdX Los dispositivos permanecen tranquilos ninguno. El RAID por hardware se trata como un único dispositivo de bloque.
  • Multitrayecto: En el mapeador multipath (/dev/mapper/mpatha); los dispositivos de ruta debajo de ninguno.

Importante: separo las pruebas según piscina y nivel de redundancia (RAID1/10 frente a RAID5/6). Los RAID de paridad son más sensibles a las escrituras aleatorias; en este caso, mq-deadline suele ganar gracias a sus plazos de lectura coherentes y a su salida ordenada.

Estrategias de optimización: paso a paso hacia un rendimiento fiable

Empiezo con una medición básica: tiempos de respuesta actuales, rendimiento, percentiles 95/99 y CPU.Carga. A continuación, solo cambio un factor, normalmente el programador, y repito la misma carga. Herramientas como fio ayudan a controlar, pero confirmo cada hipótesis con pruebas de aplicación reales. Para las bases de datos son adecuados los propios puntos de referencia, que reflejan las transacciones y el comportamiento fsync. Solo cuando la medición es estable, confirmo la elección y la documento. Por qué.

Profundidad de la cola, lectura anticipada y afinidad de la CPU

Además del programador, los parámetros de la cola influyen considerablemente en la práctica:

  • Profundidad de la cola: /sys/block//queue/nr_requests Limita las solicitudes pendientes por cola de hardware. NVMe admite una gran profundidad (alto rendimiento), mientras que los HDD se benefician de una profundidad moderada (latencia más estable).
  • Readahead: /sys/block//queue/read_ahead_kb respectivamente blockdev --getra/setra. Manténgalo algo más alto para cargas de trabajo secuenciales y bajo para cargas de trabajo aleatorias.
  • rq_affinityCon /sys/block//queue/rq_affinity En el segundo, me aseguro de que la finalización de E/S se realice preferentemente en el núcleo de CPU generador, lo que reduce los costes entre CPU.
  • rotacional: Verifico que los SSD rotacional=0 para que el núcleo no aplique heurísticas HDD.
  • Fusiones: /sys/block//queue/nomerges Puede reducir las fusiones (2=desactivado). Útil en parte para la microlatencia NVMe, pero generalmente desfavorable para los discos duros.
  • io_poll (NVMe): el sondeo puede reducir las latencias, pero requiere CPU. Lo activo específicamente en Baja latencia-Requisitos.

Ajustes del programador en detalle

Dependiendo del programador, hay disponibles ajustes precisos útiles:

  • mq-fecha límite: /sys/block//queue/iosched/read_expire (ms, típicamente pequeño), write_expire (más grande), fifo_batch (tamaño del lote), front_merges (0/1). Considero que read_expire brevemente para proteger las lecturas P95 y ajustar fifo_batch Según el dispositivo.
  • BFQ: slice_inactivo (Tiempo de inactividad para el uso de secuencias), baja latencia (0/1) para una interactividad con gran capacidad de reacción. Con bfq.weight En Cgroups controlo las cuotas relativas con mucha precisión.
  • none/noop: Apenas tornillos de ajuste, pero los Alrededores (profundidad de la cola, lectura anticipada) determina los resultados.

Siempre cambio solo un parámetro y registro estrictamente el cambio, así queda claro qué efecto ha tenido cada cosa.

Errores comunes y cómo evitarlos

Las combinaciones mixtas de HDD y SSD detrás de un controlador RAID falsean las pruebas, por lo que separo las mediciones por Grupo. No olvido que el programador se aplica por dispositivo de bloque; considero por separado los dispositivos LVM Mapper y MD. La persistencia tiende a desaparecer: sin una regla udev o un parámetro del núcleo, tras el reinicio vuelve a aparecer el valor predeterminado. Los cgroups y las prioridades de E/S suelen quedar sin utilizar, aunque mejoran considerablemente la equidad. Y siempre compruebo la profundidad de la cola, la reescritura y las opciones del sistema de archivos para que la lógica elegida alcance su potencial. muestra.

Solución de problemas: leer los síntomas de forma específica

Cuando los valores medidos cambian, interpreto los patrones y deduzco medidas concretas:

  • Alta latencia P99 con muchas lecturas: Comprobar si las escrituras desplazan a las lecturas. Probar con mq-deadline., read_expire reducir, suavizar la reversión (vm.dirty_* adaptar).
  • 100% util en HDD, rendimiento bajo: Dominan las búsquedas. Probar BFQ o mq-deadline, reducir Readahead, moderar la profundidad de la cola.
  • Buen rendimiento, pero la interfaz de usuario es irregular.: La interactividad se ve afectada. Activar BFQ, servicios críticos mediante ionice -c1 o dar preferencia a las ponderaciones de Cgroup.
  • Gran variación según la hora del día: Recursos compartidos. Aislar con cgroups, seleccionar el programador para cada grupo, trasladar las copias de seguridad a horas de menor actividad.
  • Tiempo de espera NVMe en dmesg: Backend o tema del firmware. io_poll Desactivar a modo de prueba, comprobar el firmware/controlador, verificar la redundancia de la ruta (multiruta).

En resumen: decisiones claras para el día a día del alojamiento web.

Para el almacenamiento flash y los invitados, suelo optar por Noop, para ahorrar gastos generales y dejar trabajar a los controladores. En servidores versátiles con HDD o RAID, mq-deadline ofrece una latencia fiable y una alta disponibilidad. Con muchos usuarios activos y una carga interactiva, BFQ garantiza una distribución equitativa y una capacidad de respuesta notable. Antes de cada fijación, realizo mediciones con cargas de trabajo reales y observo los efectos en P95/P99. De este modo, tomo decisiones comprensibles, mantengo los sistemas en funcionamiento y estabilizo el Servidor-Rendimiento en las actividades diarias.

Artículos de actualidad