Le planificateur d'E/S Linux décide comment le système trie, hiérarchise et envoie les accès en lecture et en écriture vers les SSD, NVMe et HDD. Dans ce guide, j'explique de manière pratique quand Noop, mq-deadline et BFQ sont le meilleur choix en matière d'hébergement – y compris le réglage, les tests et les étapes claires à suivre.
Points centraux
- Noop: surcharge minimale sur SSD/NVMe et dans les machines virtuelles
- mq-deadline: latence et débit équilibrés pour les serveurs
- BFQ: équité et réactivité dans les environnements multi-utilisateurs
- blk-mq: Conception multi-file d'attente pour matériel moderne
- Tuning: Tests par charge de travail au lieu de règles fixes
Comment fonctionne le planificateur d'E/S dans l'hébergement Linux
Un planificateur d'E/S Linux classe les demandes d'E/S dans des files d'attente, effectue des fusions et décide de la livraison au périphérique afin de Latence et d'augmenter le débit. Les noyaux modernes utilisent blk-mq, c'est-à-dire Multi-Queue, afin que plusieurs cœurs de processeur puissent déclencher des E/S en parallèle. Cela convient aux SSD NVMe, qui offrent de nombreuses files d'attente et un parallélisme élevé, ce qui réduit les files d'attente. Dans l'hébergement, des charges mixtes importantes se rencontrent souvent : les serveurs web fournissent de nombreuses petites lectures, les bases de données génèrent des écritures synchronisées, les sauvegardes génèrent des flux. Le planificateur approprié réduit les encombrements, maintient des temps de réponse stables et protège les ServeurExpérience sous contrainte.
blk-mq dans la pratique : none vs. noop et paramètres par défaut du noyau
Depuis le noyau 5.x, la conception multi-file d'attente est la voie standard. Il convient de noter que none l'équivalent „ Noop “ pour blk-mq, tandis que noop provient historiquement du chemin d'accès à file d'attente unique. Sur les périphériques NVMe, seul none disponible ; sur SATA/SAS, on voit souvent mq-deadline, en option bfq et, selon la distribution, également kyber. Les valeurs par défaut varient : NVMe démarre généralement avec none, SCSI/SATA souvent avec mq-deadline. Je vérifie donc toujours les options disponibles via cat /sys/block//queue/scheduler et je décide pour chaque appareil. Où seulement none est sélectionnable, c'est voulu – un tri supplémentaire n'apporte pratiquement aucune valeur ajoutée dans ce cas.
Noop dans l'utilisation des serveurs : quand le minimalisme l'emporte
Noop effectue principalement la fusion de blocs adjacents, mais ne trie pas, ce qui réduit considérablement la charge CPU. faible sur les SSD et NVMe, les contrôleurs et le micrologiciel prennent en charge l'ordre intelligent, de sorte qu'un tri supplémentaire dans le noyau n'apporte guère d'avantages. Dans les machines virtuelles et les conteneurs, je planifie souvent Noop, car l'hyperviseur planifie de toute façon de manière globale. Sur les disques rotatifs, je renonce à Noop, car l'absence de tri augmente les temps de recherche. Si vous souhaitez délimiter clairement le contexte matériel, examinez d'abord le type de mémoire. Il est utile de consulter NVMe, SSD et HDD, avant de lancer le planificateur déterminer.
mq-deadline : délais, ordres et priorités claires
mq-deadline attribue des délais courts aux accès en lecture et fait attendre un peu plus longtemps les accès en écriture afin de Temps de réponse Le planificateur trie également les adresses de blocs, ce qui réduit les temps de recherche, ce qui est particulièrement utile pour les disques durs et les matrices RAID. Dans les hôtes Web et de bases de données, mq-deadline offre un bon équilibre entre latence et débit. Je l'utilise volontiers lorsque les charges de travail sont mixtes et que les lectures et les écritures sont en attente en permanence. Pour le réglage fin, je vérifie la profondeur des requêtes, le comportement de réécriture et le cache du contrôleur afin que la logique Deadline soit cohérente. saisit.
BFQ : équité et réactivité pour de nombreux utilisateurs simultanés
BFQ répartit la bande passante proportionnellement et attribue des budgets par processus, ce qui est perceptible. équitable fonctionne lorsque de nombreux utilisateurs génèrent des E/S en parallèle. Les tâches interactives telles que les shells d'administration, les éditeurs ou les appels API restent rapides, même lorsque des sauvegardes sont en cours d'exécution en arrière-plan. Sur les disques durs, BFQ atteint souvent un haut niveau d'efficacité, car il exploite les phases séquentielles et utilise intelligemment les courtes fenêtres d'inactivité. Sur les SSD très rapides, cela entraîne un léger surcoût, que je mets en balance avec la réactivité notable. Ceux qui utilisent Cgroups et ioprio peuvent obtenir des garanties claires avec BFQ et éviter ainsi les désagréments causés par des voisins bruyants. éviter.
QoS au quotidien : ioprio, ionice et Cgroups v2 avec BFQ
Pour des Définition des priorités Je combine BFQ avec des règles de processus et Cgroup. Au niveau du processus, je définis avec ionice Classes et priorités : ionice -c1 (en temps réel) pour les lectures critiques en termes de latence, ionice -c2 -n7 (meilleur effort, faible) pour les sauvegardes ou les exécutions d'index, ionice -c3 (Idle) pour tout ce qui doit fonctionner uniquement pendant les temps d'inactivité. Dans Cgroups v2, j'utilise io.weight pour les proportions relatives (par exemple 100 contre 1000) et io.max pour les limites strictes, par exemple echo " 259:0 rbps=50M wbps=20M " > /sys/fs/cgroup//io.max. Avec BFQ, les pondérations sont converties de manière très précise en parts de bande passante, ce qui est idéal pour l'hébergement mutualisé et les hébergeurs de conteneurs sur lesquels Équité est plus important que la puissance brute maximale.
Comparaison pratique : quel choix de matériel convient le mieux ?
Le choix dépend fortement du type de mémoire et de l'architecture de la file d'attente, c'est pourquoi je vérifie d'abord Appareil et contrôleurs. Les SSD et NVMe bénéficient généralement de Noop/none, tandis que les disques durs fonctionnent mieux avec mq-deadline ou BFQ. Dans les configurations RAID, les SAN et les hôtes polyvalents, je préfère souvent mq-deadline, car la logique Deadline et le tri s'harmonisent bien. Les environnements multi-utilisateurs avec de nombreuses sessions interactives gagnent souvent à utiliser BFQ. Le tableau suivant résume clairement les points forts et les domaines d'application pertinents. ensemble:
| planificateur | Matériel informatique | Points forts | Faiblesses | Scénarios d'hébergement |
|---|---|---|---|---|
| Noop/aucun | SSD, NVMe, VM | Overhead minimal, fusion propre | Sans tri sur les disques durs, cela présente des inconvénients | Serveur Flash, conteneur, contrôlé par hyperviseur |
| mq-deadline | HDD, RAID, serveur polyvalent | Priorité de lecture stricte, tri, latence stable | Plus logique que Noop | Bases de données, backends Web, charges mixtes |
| BFQ | HDD, multi-utilisateurs, hôtes de type bureau | Équité, réactivité, bonnes séquences | Un peu plus de surcharge sur les SSD très rapides | Services interactifs, hébergement mutualisé, serveur de développement |
Configuration : vérifier le planificateur et le définir de manière permanente
Je commence par vérifier quel planificateur est actif, par exemple avec cat /sys/block/sdX/queue/scheduler, et note le Option entre crochets. Pour changer temporairement, j'écris par exemple echo mq-deadline | sudo tee /sys/block/sdX/queue/scheduler. Pour les paramètres persistants, j'utilise les règles udev ou les paramètres du noyau tels que scsi_mod.use_blk_mq=1 et mq-deadline dans la ligne de commande. Pour les périphériques NVMe, je vérifie les chemins d'accès sous /sys/block/nvme0n1/queue/ et effectuez la sélection pour chaque appareil. Important : je documente les modifications afin que la maintenance et la restauration puissent s'effectuer sans conjecture. réussir.
Persistance et automatisation dans l'exploitation
Au quotidien, je privilégie la répétabilité à l'automatisation. Trois méthodes ont fait leurs preuves :
- Règles udev: exemple pour tous les disques durs (rotationnel = 1)
echo 'ACTION=="add|change", KERNEL=="sd*", ATTR{queue/rotational}=="1", ATTR{queue/scheduler}="mq-deadline"' > /etc/udev/rules.d/60-io-scheduler.rules, alorsudevadm control --reload-rules && udevadm trigger. - systemd-tmpfiles: Pour des appareils spécifiques, je définis
/etc/tmpfiles.d/blk.confavec des phrases telles quew /sys/block/sdX/queue/scheduler - - - - mq-deadline, qui écrivent lors du démarrage. - Gestion de configuration: Dans Ansible/Salt, je crée des classes d'appareils (NVMe, HDD) et je distribue des paramètres par défaut cohérents, accompagnés de la documentation et de la restauration.
Remarque : ascenseur= était le paramètre du noyau pour l'ancien chemin à file d'attente unique. Dans blk-mq, je détermine le choix par appareil. Pour les piles (dm-crypt, LVM, MD), je définis le paramètre par défaut sur le périphérique supérieur. Vous trouverez plus d'informations à ce sujet ci-dessous.
Charges de travail dans l'hébergement : identifier les modèles et agir correctement
Je commence par analyser la charge : de nombreuses petites lectures indiquent des interfaces Web, des écritures synchronisées intensives sur des bases de données et des pipelines de journaux, de grands flux séquentiels sur des sauvegardes ou Archives. Des outils tels que iostat, vmstat et blktrace montrent les files d'attente, les latences et les effets de fusion. En cas de temps d'inactivité CPU notable dû à l'E/S, je renvoie à Comprendre l'attente E/S, pour éliminer les goulots d'étranglement de manière structurée. Ensuite, je teste 1 à 2 candidats planificateurs dans des créneaux horaires identiques. Seuls les résultats des mesures sont déterminants, et non l'intuition ou mythes.
Approfondir la pratique de mesure : benchmarks reproductibles
Pour prendre des décisions fiables, j'utilise des fio-Profils et confirmation par des tests réels sur les applications :
- Lectures aléatoires (Web/Cache) :
fio --name=rr --rw=randread --bs=4k --iodepth=32 --numjobs=4 --runtime=120 --time_based --filename=/mnt/testfile --direct=1 - Mix aléatoire (DB) :
fio --name=randmix --rw=randrw --rwmixread=70 --bs=8k --iodepth=64 --numjobs=8 --runtime=180 --time_based --direct=1 - Séquentiel (Sauvegarde) :
fio --name=seqw --rw=write --bs=1m --iodepth=128 --numjobs=2 --runtime=120 --time_based --direct=1
En parallèle, je me connecte iostat -x 1, pidstat -d 1 et notez les latences P95/P99 à partir de fio. Pour les diagnostics approfondis, j'utilise blktrace ou des outils eBPF tels que biolatency . Important : je mesure à la même heure, avec les mêmes fenêtres de charge et les mêmes tailles de fichiers. Je minimise les effets du cache avec direct=1 et des pré-conditions propres (par exemple, pré-remplissage sur le volume).
Systèmes de fichiers et planificateurs d'E/S : l'interaction est essentielle
Le système de fichiers influence les caractéristiques d'E/S, c'est pourquoi je vérifie très attentivement son mode journal, la profondeur de la file d'attente et le comportement de synchronisation. exactement. EXT4 et XFS fonctionnent efficacement avec mq-deadline, tandis que ZFS met beaucoup de choses en mémoire tampon et les agrège. Sur les hôtes équipés de ZFS, j'observe souvent un effet de planificateur moindre, car ZFS forme déjà la sortie. Pour les comparaisons, j'utilise des options de montage et des charges de travail identiques. Si vous évaluez les options, vous trouverez dans EXT4, XFS ou ZFS perspectives utiles sur Stockage-Réglage.
Writeback, cache et barrières : la moitié souvent négligée
Les planificateurs ne peuvent fonctionner correctement que dans la mesure où le sous-système de réécriture le permet. Je vérifie donc toujours :
- paramètre dirty:
sysctl vm.dirty_background_bytes,vm.dirty_bytes,vm.dirty_expire_centisecscontrôler quand et avec quelle agressivité le noyau écrit. Pour les bases de données, je réduis souvent les pics de rafales afin de maintenir P99 stable. - Barrières/Flush: options telles que EXT4
barrièreJe ne sauvegarde les vidages par défaut XFS que si le matériel (par exemple BBWC) les prend en charge. „ nobarrier “ sans protection électrique est risqué. - Cache d'écriture du périphérique: je vérifie les paramètres du cache d'écriture du contrôleur afin que
fsyncatterrisse réellement sur le support et pas seulement dans le cache.
En lissant Writeback, vous soulagez le planificateur : les délais restent fiables et BFQ a moins à lutter contre les vagues soudaines de flush.
Virtualisation, conteneurs et cloud : qui planifie réellement ?
Dans les VM, l'hyperviseur contrôle le flux d'E/S physique, c'est pourquoi je choisis souvent Noop/none dans l'invité afin d'éviter les doublons. logique À éviter. Sur l'hôte lui-même, j'utilise mq-deadline ou BFQ en fonction de l'appareil et de la tâche. Pour les volumes cloud (par exemple, le stockage en blocs réseau), une partie de la planification se fait en arrière-plan ; je mesure donc les latences réelles au lieu de me fier à des hypothèses. Pour les hôtes de conteneurs avec une charge très mixte, BFQ offre souvent une meilleure interactivité. Dans les clusters batch homogènes avec Flash-Only, Noop s'impose, car chaque temps CPU compte et les contrôleurs sont efficaces. travaillent.
RAID, LVM, MD et Multipath : où intervient le planificateur
Dans les piles de blocs empilés, je place le planificateur au Appareil haut de gamme car c'est là que se trouvent les files d'attente pertinentes :
- LVM/dm-crypt: Planificateur sur
/dev/dm-*respectivement/dev/mapper/Je laisse généralement les PV physiques surnone, afin d'éviter que la fusion/le tri ne se produise deux fois. - MD-RAID: Le
/dev/mdXdécider ; en dessoussdXLes appareils restent calmesnone. Le RAID matériel est traité comme un périphérique bloc unique. - multivoie: Sur le mappeur multipath (
/dev/mapper/mpatha) ; les périphériques de chemin d'accès en dessous surnone.
Important : je sépare les tests selon piscine et niveau de redondance (RAID1/10 vs RAID5/6). Les RAID à parité sont plus sensibles aux écritures aléatoires ; ici, mq-deadline l'emporte souvent grâce à des délais de lecture cohérents et une sortie ordonnée.
Stratégies de réglage : étape par étape vers une performance fiable
Je commence par une mesure de base : temps de réponse actuels, débit, 95e/99e centile et CPU.Charge. Ensuite, je ne modifie qu'un seul facteur, généralement le planificateur, et je répète la même charge. Des outils tels que fio aident à contrôler, mais je confirme chaque hypothèse à l'aide de tests d'application réels. Pour les bases de données, il convient d'utiliser des benchmarks spécifiques qui reflètent les transactions et le comportement fsync. Ce n'est que lorsque la mesure est stable que je consigne mon choix et que je le documente. Pourquoi.
Profondeur de la file d'attente, lecture anticipée et affinité CPU
Outre le planificateur, les paramètres de file d'attente ont une forte influence sur la pratique :
- Profondeur de la file d'attente:
/sys/block//queue/nr_requestsLimite les requêtes en attente par file d'attente matérielle. NVMe supporte une profondeur élevée (débit élevé), les disques durs bénéficient d'une profondeur modérée (latence plus stable). - Readahead:
/sys/block//queue/read_ahead_kbrespectivementblockdev --getra/setra. Légèrement plus élevé pour les charges de travail séquentielles, faible pour les charges de travail aléatoires. - rq_affinity: Avec
/sys/block//queue/rq_affinitysur 2, je veille à ce que l'achèvement des E/S soit prioritairement effectué sur le cœur de processeur générateur, ce qui réduit les coûts inter-processeurs. - rotationnel: Je vérifie que les SSD
rotationnelle=0pour que le noyau n'applique pas d'heuristiques HDD. - Fusions:
/sys/block//queue/nomergesPeut réduire les fusions (2 = désactivé). Utile pour la micro-latence NVMe, mais généralement désavantageux pour les disques durs. - io_poll (NVMe) : le polling peut réduire les latences, mais nécessite un CPU. Je l'active de manière ciblée pour Faible latence-exigences.
Paramètres de planification détaillés
Selon le planificateur, des réglages précis utiles sont disponibles :
- mq-deadline:
/sys/block//queue/iosched/read_expire(ms, généralement faible),write_expire(plus grand),fifo_batch(taille du lot),front_merges(0/1). Je considère queread_expirebref, pour protéger les lectures P95, et ajustefifo_batchselon l'appareil. - BFQ:
slice_idle(temps d'inactivité pour l'utilisation de la séquence),faible latence(0/1) pour une interactivité réactive. Avecbfq.weightDans les cgroups, je contrôle les parts relatives de manière très précise. - none/noop: Peu de vis de réglage, mais les Environs (profondeur de la file d'attente, lecture anticipée) détermine les résultats.
Je ne modifie toujours qu'un seul paramètre et je note rigoureusement chaque modification, afin de pouvoir identifier clairement l'effet produit par chacune d'entre elles.
Les pièges courants et comment je les évite
Les pools mixtes composés de disques durs et SSD derrière un contrôleur RAID faussent les tests, c'est pourquoi je sépare les mesures par Groupe. Je n'oublie pas que le planificateur s'applique par périphérique de bloc – je considère les mappeurs LVM et les périphériques MD séparément. La persistance a tendance à disparaître : sans règle udev ou paramètre du noyau, la valeur par défaut est rétablie après le redémarrage. Les cgroups et les priorités d'E/S restent souvent inutilisés, bien qu'ils améliorent considérablement l'équité. Et je vérifie toujours la profondeur de la file d'attente, le writeback et les options du système de fichiers afin que la logique choisie puisse exploiter tout son potentiel. montre.
Dépannage : lire les symptômes de manière ciblée
Lorsque les valeurs mesurées changent, j'interprète les tendances et j'en déduis des mesures concrètes :
- Latence P99 élevée lors de nombreuses lecturesVérifier si les écritures prennent le pas sur les lectures. Tester avec mq-deadline.,
read_expireréduire, lisser la reprise (vm.dirty_*adapter). - 100% util sur disque dur, faible débit: Rechercher les dominantes. Essayer BFQ ou mq-deadline, réduire Readahead, modérer la profondeur de la file d'attente.
- Bon débit, mais interface utilisateur saccadée: l'interactivité en pâtit. Activer BFQ, services critiques via
ionice -c1ou privilégier les pondérations Cgroup. - Forte variance selon l'heure de la journée: Ressources partagées. Isoler avec Cgroups, choisir le planificateur par pool, déplacer les sauvegardes vers les heures creuses.
- Délais d'attente NVMe dans dmesg: Backend ou thème du micrologiciel.
io_pollDésactiver à titre d'essai, vérifier le micrologiciel/pilote, vérifier la redondance du chemin (multipath).
En bref : des décisions claires pour l'hébergement au quotidien
Pour le stockage flash et les invités, j'opte souvent pour Noop, pour réduire les frais généraux et laisser les contrôleurs fonctionner. Dans les serveurs polyvalents équipés d'un disque dur ou d'un RAID, mq-deadline offre une latence fiable et une grande facilité d'utilisation. Lorsque les utilisateurs actifs sont nombreux et la charge interactive importante, BFQ garantit un partage équitable et une réactivité notable. Avant chaque fixation, je mesure avec des charges de travail réelles et j'observe les effets sur P95/P99. Cela me permet de prendre des décisions compréhensibles, de maintenir les systèmes à flot et de stabiliser la Serveur-Performance dans les activités quotidiennes.


