...

Comprendre l'attente E/S : quand un stockage lent ralentit le serveur

Hébergement I/O Wait ralentit les applications lorsque le processeur attend des disques lents et que les requêtes restent bloquées dans le sous-système de stockage. Je vais vous montrer comment identifier les temps d'attente d'E/S, classer clairement les goulots d'étranglement et Vitesse de stockage du serveur augmenter de manière ciblée.

Points centraux

  • Attente E/S indique que le processeur attend des supports de données lents.
  • Valeurs mesurées La latence, les IOPS et la profondeur de la file d'attente sont déterminants pour la vitesse.
  • Mises à niveau sur SSD/NVMe et RAID 10 réduisent considérablement les temps d'attente.
  • Mise en cache dans RAM, Redis ou Memcached soulage le stockage.
  • Suivi iostat/iotop permet de détecter rapidement les goulots d'étranglement.

I/O-Wait expliqué brièvement et clairement

Lorsque la valeur iowait augmente, le CPU attend un support de données au lieu de calculer. Cette situation se produit lorsque des processus lancent des opérations de lecture ou d'écriture et que le lecteur ne répond pas assez rapidement. Je fais la distinction entre les goulots d'étranglement CPU et les goulots d'étranglement E/S : une utilisation élevée du CPU sans iowait indique une charge de calcul, des valeurs iowait élevées indiquent un manque de vitesse de la mémoire. Les files d'attente s'allongent, ce qui Latence augmente à chaque requête, et le débit effectif diminue. Plus le nombre de requêtes d'E/S simultanées est élevé, plus le ralentissement du stockage affecte chaque application.

Symptômes typiques sur le serveur

Je remarque d'abord les problèmes d'E/S lorsque le système ralentit. Bases de données et des temps de réponse API longs. Les processus Web se bloquent lors de l'accès aux fichiers ou aux journaux, les tâches cron prennent plus de temps que prévu et les charges de travail par lots sont reportées à la nuit. La surveillance montre une profondeur de file d'attente élevée et des temps d'attente importants par E/S. Le CPU semble “ libre ”, mais les requêtes sont traitées lentement car le plaques ne parviennent pas à suivre. C'est précisément là qu'un diagnostic précis portant sur la latence, les IOPS et la longueur des files d'attente s'avère utile.

Bien interpréter les indicateurs de performance

Je mesure iowait, la latence, les IOPS, le débit et Profondeur de la file d'attente avec des outils tels que iostat, iotop, vmstat et sar. Je m'intéresse particulièrement aux valeurs distinctes pour la lecture et l'écriture, car les chemins d'écriture présentent souvent des goulots d'étranglement différents de ceux des accès en lecture. J'observe les 95e et 99e centiles de la latence, et pas seulement la valeur moyenne. Même les petits fichiers avec de nombreux accès aléatoires se comportent différemment des grands flux séquentiels. Je mets ces métriques en relation les unes avec les autres afin de mettre en évidence les véritables goulots d'étranglement.

Le tableau suivant m'aide à classer les valeurs mesurées et à prendre rapidement des décisions :

Métriques valeur indicative Remarque Prochaine étape
iowait (%) > 10–15 % pendant quelques minutes Le CPU attend clairement l'E/S Vérifier le stockage, augmenter la mémoire cache
r_await / w_await (ms) > 5 ms SSD, > 1 ms NVMe Haute Latence par opération Raccourcir le chemin d'accès E/S, tester NVMe
avgqu-sz > 1 permanent La file d'attente s'allonge Réduire le parallélisme, utiliser le cache
IOPS Nettement en dessous des attentes L'appareil est limité Vérifier le planificateur/la mise en cache/le RAID
Débit (Mo/s) Fluctue fortement Perturbateur Spikes visible Définir la QoS, planifier les tâches en arrière-plan

Bien identifier les causes

Je constate souvent qu'il y a trop de Demandes solliciter le même support de données. Des lecteurs inadaptés (HDD au lieu de SSD/NVMe) sont alors confrontés à des applications bavardes avec de nombreuses petites opérations d'E/S. De mauvais index dans les bases de données aggravent le problème, car les analyses lisent inutilement un grand nombre de blocs. L'absence de cache RAM oblige le système à accéder en permanence au support de données, même pour les ensembles de données très sollicités. Les configurations RAID sans cache Write-Back ou les micrologiciels de contrôleur défectueux augmentent également les délais de manière notable.

Mesures immédiates en cas de temps d'attente prolongé

Je réduis d'abord les excès Parallélisme pour les tâches, les travailleurs et les connexions à la base de données. Ensuite, j'augmente la part de RAM pour les caches tels que le cache de page ou le pool de tampons InnoDB. J'active le cache Write-Back (avec BBU) sur le contrôleur RAID afin d'accélérer les accès en écriture. Je déplace les processus de sauvegarde et d'ETL hors des heures de pointe et je découple les accès en écriture aux journaux. Enfin, j'optimise la taille des fichiers et la granularité des lots afin que le support de données fonctionne plus efficacement.

Mise à niveau du stockage : HDD, SSD ou NVMe ?

Je choisis la Technique En fonction de la charge de travail : de nombreux petits accès nécessitent NVMe, les flux séquentiels importants fonctionnent bien avec SSD, les données d'archives restent sur HDD. Les disques NVMe modernes offrent un nombre d'IOPS nettement supérieur avec une latence très faible, ce qui réduit considérablement l'iowait. Lorsque le budget est important, je place les bases de données critiques sur NVMe et les données secondaires sur SSD/HDD. Pour prendre mes décisions, je m'aide d'une comparaison telle que NVMe vs SSD vs HDD pour la technique, les coûts et les effets. Je réduis ainsi les temps d'attente là où ils sont les plus perceptibles pour l'utilisateur.

Utilisation ciblée du RAID et de la mise en cache

Je mise pour Performance J'utilise souvent RAID 10, car il traite plus rapidement les accès en lecture et en écriture et offre une redondance. J'utilise plutôt RAID 5/6 pour les charges de travail à forte intensité de lecture, où les pénalités d'écriture ont moins d'impact. Une unité alimentée par batterie permet un cache de réécriture sécurisé sur le contrôleur et accélère considérablement les transactions. De plus, Redis ou Memcached accélèrent l'accès aux données fréquemment utilisées dans la mémoire vive. Cela me permet de soulager les disques et de réduire durablement l'iowait.

Choisir correctement les systèmes de fichiers et les planificateurs d'E/S

Je recourt à des Charges de travail Souvent XFS pour sa bonne parallélisation et sa gestion robuste des métadonnées. J'utilise ZFS lorsque j'ai besoin de checksumming, de snapshots et de compression et que je dispose de suffisamment de RAM. Ext4 reste solide pour de nombreuses tâches quotidiennes, mais peut prendre du retard en cas de très nombreux inodes et flux parallèles. Sur les SSD, j'utilise des planificateurs de type Deadline ou None/None, tandis que sur les HDD, une planification de type CFQ peut être utile. J'ajuste avec précaution les paramètres de lecture anticipée et la profondeur des files d'attente afin qu'ils correspondent au profil d'accès.

Nivellement, QoS et priorités

Je combine NVMe rapide pour les tâches intensives Données avec SSD/HDD pour les contenus froids, c'est-à-dire un véritable stockage hiérarchisé. Ainsi, je ne paie pas partout pour une latence optimale, mais j'en profite là où cela compte. Avec QoS, je limite les tâches d'arrière-plan gourmandes en bande passante afin que les transactions critiques restent stables. Une approche pratique passe par Stockage hybride et des classes claires pour les cycles de vie des données. Cette combinaison maintient l'iowait à un niveau bas et évite les surprises en cas de charge importante.

Alléger les bases de données et les applications

J'économise des E/S en utilisant la Requêtes Je définis des index rigoureux et adaptés. J'élimine les requêtes N+1, j'optimise les jointures et je réduis les transactions bavardes. Je dimensionne les pools de connexions de manière à ce qu'ils n'encombrent pas le stockage. Je lisse les pics d'écriture à l'aide du batching et des files d'attente asynchrones afin que les pics ne mobilisent pas toutes les ressources en même temps. J'écris les logs de manière groupée, j'augmente les rotations et je minimise les accès de synchronisation lorsque les exigences de cohérence le permettent.

Stratégie de surveillance et alertes intelligentes

Je mesure en continu iowait, les percentiles de latence, avgqu-sz, IOPS et Débit. Je ne déclenche des alertes qu'en cas de tendances, et non en cas de pics courts, afin que les équipes restent concentrées. Je sépare les tableaux de bord pour la capacité, la latence et les taux d'erreur afin que les causes soient rapidement visibles. Le traçage des requêtes montre quels chemins sollicitent le plus le stockage. Pour les applications critiques en termes de latence, cela m'aide. Hébergement à micro-latence, afin de réduire globalement les temps de réaction.

Pratique : parcours diagnostique étape par étape

Je procède de manière structurée afin d'attribuer sans aucun doute les temps d'attente E/S. Je vérifie d'abord à l'échelle du système avec vmstat et sar si iowait est élevé et si des changements de contexte et des SoftIRQ sont simultanément visibles. Ensuite, je vérifie pour chaque appareil avec iostat -x si r_await/w_await et avgqu-sz augmentent. Enfin, j'utilise iotop/pidstat -d pour identifier les processus qui déplacent le plus d'octets ou qui causent le plus de temps d'attente.

  • Test rapide avec tmpfs : je répète les processus critiques à titre d'essai sur des disques tmpfs/RAM. Si la latence diminue considérablement, le support de données est le goulot d'étranglement.
  • Vérification de dmesg/smartctl : une accumulation d'erreurs, de réinitialisations ou de réallocations indique des problèmes matériels ou de câblage.
  • Comparaison entre lecture et écriture : un w_await long avec un faible taux d'écriture indique un cache du contrôleur, des paramètres de barrière ou une charge de synchronisation.

Je sépare rapidement : conception de l'application et parallélisme, système de fichiers/contrôleur ou support physique. Ensuite, j'optimise segment par segment, au lieu de tout modifier à l'aveuglette.

Virtualisation et conteneurs : désamorcer les voisins bruyants

Dans les machines virtuelles et les conteneurs, j'évalue toujours iowait en tenant compte des ressources partagées. Les hyperviseurs surchargés génèrent des latences variables, même si le processeur invité semble “ libre ”. Les périphériques blocs virtuels (virtio, SCSI émulé) et le stockage réseau ajoutent des couches de latence supplémentaires. Je m'assure d'obtenir des engagements IOPS/débit dédiés, je limite les tâches gourmandes en rafales et je répartis les charges de travail bruyantes entre les hôtes.

  • cgroups/Containers : je définis io.weight ou io.max afin que les tâches secondaires ne “ vident ” pas le stockage.
  • StorageClass/Volumes : je choisis des classes adaptées au profil de charge de travail (aléatoire ou séquentiel) et sépare les journaux/WAL des données.
  • VirtIO/NVMe : je privilégie les pilotes de paravirtualisation modernes et vérifie le nombre de files d'attente par vCPU pour un parallélisme maximal sans surcharge.

Optimisation du système d'exploitation et du noyau avec discernement

J'ajuste le système d'exploitation là où cela apporte une aide mesurable. Les profils de réglage trop agressifs ne font souvent que créer de nouveaux problèmes. Je commence par des étapes conservatrices et documentées, et je mesure les résultats entre chacune d'elles.

  • Writeback : je limite vm.dirty_background_ratio et vm.dirty_ratio afin que le noyau écrive les données à temps dans des lots ordonnés et lisse les pics.
  • Read-Ahead : j'adapte le Read-Ahead à chaque appareil en fonction du modèle d'accès (faible pour les accès aléatoires, plus élevé pour les accès séquentiels) afin d'éviter la lecture de pages inutiles.
  • Planificateur/blk-mq : sur NVMe, j'utilise “ none ”/mq optimisé, sur HDD, éventuellement orienté équité. Je vérifie si la profondeur de la file d'attente est adaptée à chaque appareil et à chaque CPU.
  • IRQ/NUMA : je répartis les interruptions NVMe entre les cœurs (affinité IRQ), j'évite le trafic inter-NUMA et je conserve les applications et les données “ localement ”.
  • Gouverneur CPU : en production, je règle généralement sur « performance » afin que les changements de fréquence n'entraînent pas de latence supplémentaire.

Options de montage et détails du système de fichiers

Grâce à des options de montage adaptées, j'évite les E/S inutiles et j'améliore la cohérence là où cela compte. J'utilise relatime/noatime pour réduire les accès en écriture Atime. Sur les SSD, j'utilise fstrim périodique au lieu de discard continu si les disques souffrent de discard. J'adapte les paramètres de journalisation à la charge de travail : des intervalles de validation courts augmentent la durabilité, tandis que des intervalles longs réduisent le taux d'écriture.

  • Ext4 : data=ordered reste une bonne norme ; lazytime réduit la pression d'écriture des métadonnées.
  • XFS : je fais attention aux paramètres du journal (taille/tampon) afin que la charge des métadonnées ne devienne pas un goulot d'étranglement.
  • ZFS : je prévois suffisamment d'ARC et adapte la taille des enregistrements aux profils de données ; je choisis consciemment les politiques de synchronisation et n'ajoute SLOG que si cela apporte une valeur ajoutée cohérente.

Benchmarking : réaliste plutôt qu'optimiste

Je mesure à l'aide de profils FIO qui reflètent la charge de travail réelle : tailles de blocs de 4k/8k pour OLTP, 64k/1M pour les flux, rapports lecture/écriture mixtes, profondeurs de file d'attente correspondant à l'application. Je fais la distinction entre les exécutions “ froides ” et “ chaudes ”, je préconditionne les SSD et je considère l'état stable, pas seulement les premières secondes. J'évalue les 95e et 99e centiles, car c'est là que se trouve l'expérience utilisateur.

  • Chemin unique ou multi-tâches : je teste d'abord par appareil, puis en parallèle, afin de comprendre la mise à l'échelle et les interférences.
  • Influences du cache : vider délibérément le cache de la page ou le mesurer de manière ciblée afin de séparer les performances de l'appareil des accès à la mémoire vive.
  • A/B : Je documente l'optimisation avant/après de manière identique afin que les améliorations soient incontestables.

Chiffrement, compression et déduplication

Je tiens compte du fait que les couches cryptographiques et la compression modifient les caractéristiques d'E/S. dm-crypt/LUKS peut augmenter la latence sans accélération matérielle ; avec AES-NI, la charge CPU reste souvent modérée. Une compression légère (par exemple LZ4) réduit le volume d'E/S et peut être plus rapide malgré l'utilisation du CPU, en particulier avec des supports lents. Les mécanismes de déduplication augmentent le travail sur les métadonnées – ils conviennent aux scénarios d'archivage, mais moins aux OLTP critiques en termes de latence.

Maîtriser les sauvegardes, la maintenance et les tâches en arrière-plan

Je planifie les sauvegardes, les analyses et les rotations de manière à ne pas enfreindre les SLO. Je limite le débit, je définis ionice/nice et je divise les longues exécutions en petites étapes pouvant être poursuivies. Les sauvegardes basées sur des instantanés réduisent le verrouillage et la pression sur les E/S. Pour le traitement des journaux, j'utilise des tampons et des files d'attente dédiées afin que les pics d'écriture ne perturbent pas le trafic de production.

  • Séparation des chemins : journaux WAL/transactions sur des supports rapides, données en vrac sur des niveaux de capacité.
  • Cycles de maintenance : fstrim régulier, vérifications du système de fichiers pendant les fenêtres de maintenance et mise à jour du micrologiciel du contrôleur vers des versions stables.
  • Limitation : les limites de bande passante pour ETL/sauvegarde maintiennent les latences p99 stables.

Planification des capacités et SLO pour le stockage

Je planifie le stockage non seulement en fonction de la capacité, mais aussi en fonction des budgets de latence. Pour les chemins importants, je définis des valeurs cibles pour p95/p99 et conserve une marge de 20 à 30 %. Je vérifie les taux de croissance et les profils de charge tous les trimestres ; si la profondeur des files d'attente augmente sous une charge normale, je procède à une mise à l'échelle plus tôt que tard. Les stratégies de déploiement avec charge Canary permettent de tester le comportement des E/S des nouvelles versions avant que le trafic ne soit complet.

Modèles de dépannage pour le quotidien

Je résous les problèmes récurrents typiques à l'aide de recettes fixes. En cas de fluctuations importantes du débit, je réduis les tâches en masse et augmente les caches. Si w_await est constamment élevé, je vérifie Write-Back, Barriers et l'intensité de la synchronisation. Si avgqu-sz est élevé, je réduis le parallélisme côté application et répartis les hotspots sur plusieurs volumes. Si seuls certains locataires sont affectés, le problème vient souvent de la taille de la requête ou du pool, et non du stockage dans son ensemble.

Je documente les décisions à l'aide de valeurs mesurées et les relie aux déploiements et aux modifications de configuration. Cela permet de voir clairement ce qui a vraiment aidé et ce qui n'était que le fruit du hasard.

En bref

Je lis Attente E/S Un message clair : le support de données détermine la vitesse. Une bonne mesure me permet de déterminer si la latence, les IOPS ou les files d'attente constituent un facteur limitant. Je peux alors décider d'augmenter la mise en cache, d'ajuster le parallélisme, de simplifier les requêtes ou de mettre à niveau le stockage. NVMe, RAID 10 avec cache en écriture différée, systèmes de fichiers adaptés et QoS réduisent sensiblement les temps d'attente. Je maintiens ainsi l'io wait hosting à un faible niveau et fournis des réponses rapides, même lorsque la charge augmente.

Derniers articles