Je montre comment linux dirty et le « dirty background ratio » permettent de contrôler le cache de page et, par là même, d'influencer le débit d'écriture, la latence et la sécurité des données. Vous pouvez ainsi définir des seuils précis qui déclenchent les opérations de vidage du cache en temps opportun, évitent les blocages et améliorent les performances d'écriture de vos charges de travail.
Points centraux
Pour commencer, je vais brièvement résumer les points essentiels avant d'approfondir le sujet.
- Pages osées mise en mémoire tampon des écritures dans la RAM et regroupe de nombreux petits accès en opérations d'E/S plus efficaces.
- dirty_background_ratio lance des threads Flusher en arrière-plan, ce qui permet de limiter discrètement la quantité de données indésirables.
- dirty_ratio ralentit les processus d'écriture lorsque la limite stricte est dépassée.
- Relation Ces deux valeurs déterminent les pics de latence, le débit et la taille de la mémoire tampon.
- Variantes d'octets (dirty_bytes) permettent un contrôle plus précis et absolu sur les gros serveurs.
Comprendre les « Dirty Pages »
Lorsqu'un processus écrit des données, celles-ci sont d'abord stockées dans le Cache de page et sont marquées comme „ sales “ jusqu’à ce que le noyau puisse les vider sur le support de stockage. Cette mise en mémoire tampon accélère les applications, car la RAM réagit plus rapidement que n’importe quel SSD ou disque dur, et les petites écritures s’agrègent pour former de grands transferts séquentiels. Je garde toujours à l’esprit la quantité de „ saleté “ que j’autorise, car un tampon trop important peut allonger les files d’attente ou exposer davantage de données non sauvegardées en cas de plantage. Comprendre ce fonctionnement permet de prendre de meilleures décisions concernant le writeback, la latence et la pression sur la mémoire. Un bref article de fond sur le Cache de réécriture permet de bien cerner ce mécanisme.
Sécurité des données, fsync et fenêtre de plantage
Ces limites n'influencent pas seulement les performances, mais aussi ta fenêtre de risque. Je fais un calcul approximatif à l'aide d'une règle empirique simple : la quantité maximale de données non validées divisée par le débit durable de l'appareil donne, en gros, le temps nécessaire pour vider la mémoire tampon. Exemple : si j’autorise 4 Go de données « sales » et que le support cible atteint un débit de 500 Mo/s, l’écriture complète prendra environ 8 secondes. Pendant ce laps de temps, en cas de coupure de courant ou de « kernel panic », les dernières écritures risquent d’être perdues.
Les applications peuvent fermer la fenêtre en fsync() ou fdatasync() réduire, car ces appels obligent le système de fichiers à écrire des données (et, selon le mode de journalisation, également des métadonnées) sur le support. C'est plus coûteux, mais essentiel pour les bases de données ou les journaux. Je veille à ce que mes limites de données sales correspondent au comportement de synchronisation : fréquentes fsync()-Les visites bénéficient d'un taux plus bas dirty_ratio, afin que le noyau n'applique pas de limitation supplémentaire alors que la persistance s'effectue de toute façon régulièrement. À l'inverse, pour les journaux qui utilisent beaucoup l'ajout en fin de fichier et qui sont rarement vidés, je peux autoriser des tampons plus importants – toujours en tenant compte du risque de perte accepté.
Les barrières et l'ordre d'écriture sont également importants : les systèmes de fichiers modernes utilisent des commandes FUA/Flush pour vider correctement les caches des contrôleurs. Sur les supports dépourvus de protection contre les coupures de courant (PLP), des tampons de grande taille augmentent le risque ; avec la PLP ou une protection du cache d'écriture, des tampons plus volumineux sont souvent acceptables.
Dirty Background Ratio : le seuil flou
Avec dirty_background_ratio Je définis à partir de quel pourcentage de l'espace de stockage disponible les threads de vidage commencent à écrire en arrière-plan. Cette valeur ne bloque pas les applications, mais lance discrètement les opérations de nettoyage afin d'éviter que la mémoire tampon ne déborde. Des valeurs faibles entraînent des écritures en arrière-plan plus fréquentes mais plus régulières et lissent les pics de latence. Des valeurs plus élevées permettent d’accumuler davantage de données dans le tampon, ce qui augmente le débit lors d’écritures séquentielles volumineuses, mais peut provoquer des pics d’E/S considérables en cas de vidage soudain. Les valeurs par défaut se situent généralement autour de 10 %, mais j’ajuste cette limite en fonction du support, de la charge de travail et des exigences de sécurité.
Dirty Ratio : le freinage brutal
Le paramètre dirty_ratio indique le seuil à partir duquel le noyau limite les processus en écriture jusqu’à ce qu’un nombre suffisant de pages ait été réécrit. Cette limite stricte protège la mémoire contre un afflux de données non persistantes et a donc un impact direct sur les applications dès qu’elles tentent de poursuivre leur production. Pour les bases de données, je règle cette valeur plutôt bas afin que les requêtes conservent des temps de réponse constants et qu’il n’y ait pas de longues phases de vidage. Pour les tâches de sauvegarde, en revanche, j’utilise des tampons plus généreux afin de transférer efficacement de grands blocs de données. Les valeurs par défaut habituelles varient entre 20 et 40 %, mais j’adapte toujours cette plage à la charge réelle.
Interactions et relations typiques
Ces deux valeurs limites fonctionnent comme Tandem et ne déploient leurs effets qu’ensemble. Je maintiens toujours la valeur de `dirty_background_ratio` inférieure à celle de `dirty_ratio`, afin que le noyau démarre à temps en arrière-plan et que le freinage brutal ne se déclenche que rarement. En règle générale, je choisis souvent entre un quart et la moitié de la limite stricte, soit par exemple 5–10 pour 20. Ainsi, le « writeback » démarre suffisamment tôt sans réduire inutilement le débit. Si l’on ne respecte pas ce rapport, on constate soit une limitation trop précoce, soit un traitement en arrière-plan trop tardif, accompagné de pics de latence perceptibles.
Contrôle par périphérique et granularité de la couche de blocs
Outre les limites globales, il est intéressant de se pencher sur le niveau des périphériques. Linux répartit la charge « sale » via ce qu'on appelle Appareils pris en charge (bdi). Dans /sys/class/block//bdi/ Je trouve que des paramètres tels que max_ratio, qui déterminent la part du « Dirty Budget » global autorisé qu'un périphérique individuel peut utiliser. Sur les systèmes équipés à la fois de disques lents et rapides, je limite les disques lents afin qu'ils ne deviennent pas un goulot d'étranglement.
La limitation au niveau de la couche de blocs via /sys/block//queue/wbt_lat_usec (Writeback Throttling). Je définis ainsi une latence cible ; le noyau limite alors la charge d'écriture dès que cette latence cible est dépassée. Avec les disques durs SATA, je préfère définir des valeurs prudentes afin de préserver l’interactivité. Sur les disques NVMe très rapides, je désactive ou augmente la latence cible afin que le contrôleur puisse exploiter pleinement son parallélisme. Je choisis le planificateur d'E/S (mq-deadline, BFQ, none) en fonction des besoins : BFQ est utile pour les systèmes interactifs à charge mixte, tandis que none ou que mq-deadline donne souvent les meilleurs résultats pour les tâches de débit pur sur NVMe.
C'est l'interaction qui est déterminante : est-ce que dirty_background_ratio même si elle est faible, mais que l'appareil est limité de manière stricte par le WBT, des congestions visibles apparaissent tout de même. Je calibre donc ces deux niveaux ensemble : les limites « dirty » globales pour la taille du tampon, et la couche de blocs pour la protection contre la latence.
Ratio vs. octets : valeurs par défaut et variantes
Sur les systèmes très RAM Les pourcentages atteignent rapidement des ordres de grandeur absolus importants. Je préfère alors définir des limites maximales absolues avec `dirty_bytes` et `dirty_background_bytes`, afin de limiter clairement la taille de la mémoire tampon à environ 2 à 8 Go. Cela dissocie la gestion des niveaux de mémoire très fluctuants et permet de maintenir la quantité de données non persistantes à un niveau prévisible. Le choix reste dynamique : pour les petits serveurs disposant de peu de RAM, les pourcentages suffisent souvent amplement. Ceux qui disposent d’une grande capacité ont souvent plus de facilité à planifier avec des valeurs en octets.
| Paramètres | Signification | Défauts typiques | Quand faut-il changer ? | Remarque |
|---|---|---|---|---|
| vm.dirty_background_ratio | Lancement du Rafraîchissement de l'arrière-plan en pourcentage | ≈ 10% | En cas de fluctuations de latence ou de SSD/NVMe très rapides | Plus la valeur est faible, plus la latence est régulière ; plus elle est élevée, plus la mémoire tampon est importante |
| vm.dirty_ratio | Dur limite de régulation en pourcentage | ≈ 20–40% | Plus faible pour les bases de données, plus élevé pour les sauvegardes | Trop élevé → risque de blocages lors du flush |
| vm.dirty_background_bytes | Lancement du vidage en arrière-plan dans Octets | Désactivé lorsque Ratio est utilisé | Grande mémoire vive, cibles de tampon fixes | Remplace les paramètres Ratio |
| vm.dirty_bytes | Limite stricte de la modération dans Octets | Désactivé lorsque Ratio est utilisé | Grande mémoire vive, plafond prévisible | Remplace les paramètres Ratio |
Scénarios de charge de travail et recommandations
Les charges d'écriture séquentielles telles que Sauvegardes bénéficient de tampons importants et d'une écriture en arrière-plan modérée, car le noyau peut, dans l'ensemble, écrire sur le support. Je règle souvent ici le paramètre `dirty_ratio` entre 30 et 40 % et le paramètre `dirty_background_ratio` entre 10 et 20 %. Les bases de données et les petites applications à E/S aléatoires ont besoin d’une latence prévisible ; c’est pourquoi j’opte systématiquement pour 10 à 15 % de latence « dure » et 3 à 5 % de latence « souple ». Pour les serveurs mixtes (Web et applications), des valeurs comprises entre 15 et 20 % pour le « hard » et entre 5 et 10 % pour le « soft » s’avèrent être un bon compromis. Ces fourchettes servent de point de départ ; ensuite, ce sont les mesures réelles de votre système qui priment.
Aspects liés au système de fichiers et options de montage
Le chemin de réécriture aboutit au système de fichiers – dont la stratégie détermine les latences et la sécurité. Ext4 avec data=ordonné (Par défaut) écrit les données utiles avant la validation du journal ; data=retour à l'écriture réduit la latence, mais expose les données anciennes à des risques en cas de plantage. Le paramètre commit= (secondes) détermine la fréquence à laquelle le journal est validé. Des intervalles plus courts réduisent les pertes de données, mais entraînent davantage d'opérations d'E/S. XFS utilise une architecture de journalisation éprouvée ; les grands logbsize et un alignement adéquat facilitent les tâches de traitement en continu. Btrfs regroupe les écritures grâce à la technologie « copy-on-write » : cela stabilise les latences, mais peut entraîner une fragmentation en cas de petites écritures aléatoires et de SSD à capacité limitée. Des options telles que nodatacow peuvent aider à défragmenter certains chemins ou de manière ciblée lorsque des pics de latence se produisent.
Je tiens également à souligner relatime/noatime (réduit les écritures de métadonnées), lazytime (mtime/atime plus persistants), et les barrières de journalisation. C'est justement sur les contrôleurs RAID ou dans les machines virtuelles que la sémantique correcte du cache est déterminante : des caches d'écriture mal configurés réduisent à néant tout travail de « dirty tuning ».
E/S directes, O_SYNC et comportement de l'application
Toutes les applications ne passent pas par le cache de pages. Avec O_DIRECT ou O_SYNC/O_DSYNC Certains processus contournent certaines parties du cache ou exigent une persistance immédiate. Les bases de données écrivent généralement un WAL/journal de reprise de manière synchrone et les zones de données de manière asynchrone. Je calibre les seuils de « dirty » en particulier pour les chemins asynchrones, tandis que je garantis une latence faible aux chemins synchrones grâce à des journaux rapides (NVMe, LUN dédiés). Lorsque les applications effectuent très fréquemment fsync() lorsqu'on appelle cette fonction, les grandes mémoires tampons ne sont pas d'une grande utilité : la latence dépend alors davantage du contrôleur, de la profondeur de la file d'attente et du planificateur d'E/S que de dirty_ratio.
Des réglages pratiques, étape par étape
Avant chaque modification, je vérifie la valeurs réelles avec sysctl vm.dirty_ratio et sysctl vm.dirty_background_ratio, afin de consigner la situation initiale. Pour les tests à court terme, je note les valeurs directement après /proc/sys/vm/par exemple echo 15 > /proc/sys/vm/dirty_ratio et echo 5 > /proc/sys/vm/dirty_background_ratio. Si l'ajustement est permanent, je le sauvegarde dans /etc/sysctl.conf ou /etc/sysctl.d/*.conf. J'apporte les modifications à l'aide de sysctl -p immédiatement, afin que je puisse mesurer l'effet dans les plus brefs délais. Ceux qui souhaitent approfondir le sujet des règles du système bénéficieront de conseils pratiques sur Réglage des paramètres sysctl sur des serveurs de production.
Déterminer des valeurs : exemples de calculs
J'aime bien commencer par des chiffres concrets. Exemple n° 1 : serveur web/d'applications avec 64 Go de RAM, NVMe. L'objectif est d'obtenir une latence faible. Je configure dirty_background_bytes=1073741824 (1 Go) et dirty_bytes=3221225472 (3 Go). Avec un débit NVMe soutenu de 2 Go/s, cela correspond à environ 0,5 à 1,5 seconde pour vider le disque – ce qui est idéal pour les charges interactives. Exemple 2 : nœud de sauvegarde avec 128 Go de RAM, RAID SATA rapide à 800 Mo/s. Je choisis dirty_background_ratio=10, dirty_ratio=35. En valeur absolue, cela représente environ 12,8 Go et 44,8 Go ; le RAID met entre 16 et 56 secondes pour se vider. Ce n'est pas grave, car cette tâche n'est pas interactive.
Exemple 3 : serveur de base de données avec 256 Go de RAM, journal séparé sur NVMe, données sur une baie de SSD. Je fixe des limites strictes pour éviter les valeurs aberrantes : dirty_background_bytes=2147483648 (2 Go), dirty_bytes=8589934592 (8 Go). Cela permet de prévoir la taille de la fenêtre de crash et de réduire les ralentissements brutaux lors des points de contrôle.
Calendrier des réévaluations et paramètres associés
Outre les valeurs limites, les facteurs suivants ont une influence Minuteur le comportement de réécriture et, par conséquent, la fluidité des applications. Avec vm.dirty_writeback_centisec je contrôle l'intervalle pendant lequel le « kernel flusher » est réveillé, tandis que vm.dirty_expire_centisecs définit l’âge maximal autorisé pour les pages sales. Des intervalles plus courts entraînent des vidages plus fréquents mais de plus petite taille, tandis que des intervalles plus longs permettent d’économiser des appels d’E/S, mais risquent de générer des lots plus volumineux. Je n'ajuste ces valeurs que lorsque les mesures révèlent de réels inconvénients, par exemple des vidages trop rares sur des disques NVMe rapides. En procédant de manière méthodique, on évite les fluctuations entre une activité de réécriture trop intense et une activité trop lente.
Suivi et réglage fin
Après avoir effectué quelques ajustements, je constate que en continu les indicateurs permettant de mettre en évidence les réussites et les effets secondaires. Dans /proc/meminfo Je vérifie les paramètres „ Dirty “ et „ Writeback “ pour connaître les niveaux de la mémoire tampon et les opérations de vidage en cours. Des outils tels que iostat, sar ou atop me permettent de visualiser le débit, les files d'attente et les tendances en matière de latence. Cet article sur le sujet constitue une bonne introduction aux métriques : Analyser l'attente d'E/S. Ce n'est qu'en me basant sur ces données que je réduis ou augmente les limites par petites étapes, afin d'éviter tout effet secondaire inattendu.
Conteneurs, cgroups et répartition équitable
Dans les environnements de conteneurs, les charges de travail partagent les mêmes mécanismes du noyau. Le « Cgroup-Writeback » garantit que les pages sales soient attribuées à leur source. J'utilise les contrôleurs d'E/S des cgroups (blkcg) pour limiter la bande passante ou les IOPS par conteneur lorsque certains locataires effectuent une mise en mémoire tampon trop intensive. Limites absolues en octets au niveau de l'hôte (dirty_bytes) pour éviter qu'un seul visiteur n'épuise tout le budget « dirty ». De plus, je limite l'espace de stockage via memory.max, afin que le writeback ne réagisse pas seulement en cas de pression globale. L'objectif reste le même : aucune charge d'invité ne doit entraîner de limitations à l'échelle de l'hôte du dirty_ratio imposer.
Environnements d'hébergement et machines virtuelles
Dans les configurations multi-clients et les machines virtuelles, je veille à ce que Surréservation de la mémoire vive (RAM) et des E/S, car les limites en pourcentage y ont un impact différent. Des limites absolues en octets peuvent empêcher certains invités d'accumuler trop de mémoire tampon et de ralentir leurs voisins. Je tiens compte de la déduplication de la mémoire, du « ballooning » et des caches des contrôleurs, car ils viennent se superposer aux effets de mise en mémoire tampon. Pour les serveurs gérés, il est avantageux que le fournisseur définisse des valeurs par défaut pertinentes afin que les clients bénéficient de temps de réponse constants. Ceux qui exploitent leurs propres nœuds tirent profit de paramètres de profil clairement définis pour chaque classe de charge de travail.
Idées reçues et obstacles courants
- „ Plus de marge = un débit toujours plus élevé. “ Ce n'est pas le cas pour les charges de travail à caractère aléatoire ou les périphériques dont la profondeur de file d'attente est faible. Des tampons trop volumineux génèrent des pics de vidage et des files d'attente.
- „ dirty_ratio n'a pas d'incidence sur les lectures. “ Indirectement, si : les phases de réécriture agressives évincent les pages du cache et augmentent les latences de lecture.
- „ Les octets et la raison vont de pair. “ Non. Si tu utilises les variantes « Bytes », elles annulent leurs équivalents « Ratio ». Reste clair.
- „ fsync() rend les limites de données modifiées (Dirty Limits) sans importance. “ Non. Même si des synchronisations fréquentes réduisent la fenêtre de risque, le reste de la charge reste soumis aux valeurs limites.
- „ Un support de données rapide résout tous les problèmes. “ Pas si la couche de bloc est ralentie (WBT) ou si le système de fichiers est monté de manière non optimale.
- „ Drop_caches est un outil d'optimisation. “ Vider le cache fausse les mesures et aggrave les pics de latence. En production, j'évite de le faire.
Dépannage : symptômes typiques et solutions
S'accumulent Pics de latence, je commence par abaisser le seuil d'arrière-plan afin que les opérations de vidage commencent plus tôt et que les pics d'écriture importants se produisent moins souvent. Si certaines applications se bloquent par intermittence, cela signifie généralement que la limite stricte est trop élevée ou que le support ne parvient pas à gérer les pics de vidage générés. Dans de tels cas, je réduis la valeur de `dirty_ratio`, je vérifie les paramètres de lecture anticipée et j’examine les options de journalisation du système de fichiers. Avec du matériel NVMe très rapide, j’augmente progressivement le seuil d’arrière-plan afin de ne pas limiter artificiellement le débit. Après chaque modification, je me fie aux résultats des mesures, et non à mon intuition.
Bilan succinct pour la pratique
Avec peu de Vis de réglage Je contrôle la manière dont Linux met en mémoire tampon les données d'écriture, le moment où les flusher se lancent et celui où le noyau ralentit. Le « Dirty Background Ratio » assure un nettoyage en arrière-plan discret, tandis que le « Dirty Ratio » limite plus strictement la consommation de RAM. Le rapport entre ces deux valeurs détermine si votre système privilégie des latences régulières ou un débit maximal. Je documente les valeurs par défaut, j’apporte des modifications par petites étapes et j’analyse systématiquement les mesures. Il en résulte une configuration qui équilibre raisonnablement la charge de travail, le support et le risque, et qui se révèle sensiblement plus rapide dans la pratique.


