Taux de cache ZFS : quand ils comptent et quand ils ne comptent pas

Cet article vous a aidé ?

Vous êtes de garde. La base de données est lente. Quelqu’un poste une capture d’écran : « ARC hit ratio est tombé à 72 % ! » et une douzaine de personnes décident que c’est Le Problème.
On peut presque entendre la demande de budget pour plus de RAM se rédiger toute seule.

Parfois ils ont raison. Souvent non. Les taux de cache ZFS sont comme une météo : utiles pour planifier, inutiles pour blâmer.
C’est le guide terrain pour savoir quand ils sont pertinents — sans transformer votre stockage en foire scientifique.

Ce que mesurent réellement les taux de cache ZFS

ZFS dispose d’un cache principal en mémoire appelé ARC (Adaptive Replacement Cache). Il dispose aussi d’un cache secondaire optionnel sur des
périphériques rapides appelé L2ARC. Les deux caches suivent les « hits » et les « misses », et les outils calculent volontiers un ratio de hit qui ressemble à un KPI.

Voici le piège : un « hit » n’est pas la même chose que « rapide » et un « miss » n’est pas la même chose que « lent ». Un taux de hit indique d’où
la donnée a été servie, pas si le système a atteint des cibles de latence, pas si la charge est saine, et pas si votre pool est saturé.

ARC n’est pas un unique compartiment

ARC contient à la fois des données (blocs de fichiers) et des métadonnées (dnode, blocs indirects, entrées de répertoire, etc.). De nombreuses charges
dépendent fortement du caching des métadonnées. Par exemple, un système de fichiers avec des millions de petits fichiers peut sembler « rapide » principalement parce que les métadonnées restent chaudes,
même si les blocs de données sont froids.

ARC conserve aussi plusieurs « listes » en interne (MRU/MFU et leurs variantes « ghost ») pour équilibrer récence et fréquence. Cela compte parce qu’un hit peut être
« nous l’avons vu récemment » ou « nous le voyons constamment », ce qui a des implications de réglage différentes.

L2ARC n’est pas une extension magique de la RAM

L2ARC stocke des blocs sur SSD/NVMe pour réutilisation. Ça sonne comme « de la RAM moins chère ». En pratique, c’est « un cache SSD avec surcharge de gestion ». L2ARC
a besoin d’ARC pour l’indexer. Si vous manquez de RAM, ajouter L2ARC peut paradoxalement vous rendre plus à court de mémoire.

Les hits sont comptés par requête, pas par résultat métier

ZFS peut satisfaire une requête depuis ARC, L2ARC ou le disque. Il peut aussi anticiper des lectures (prefetch), compresser, dédupliquer (si vous avez activé cette option)
et regrouper les E/S. Votre application subit une latence de bout en bout façonnée par le CPU, les verrous, les files d’attente I/O, les commits de txg et le comportement sync.
Le taux de hit est un prisme, pas la vérité.

Un mantra pratique : la performance, c’est la latence sous charge, pas les pourcentages de cache.

Une citation à garder sur un post-it : « L’espoir n’est pas une stratégie. » — General Gordon R. Sullivan.
Les ratios de cache sont l’endroit où l’espoir se donne l’air mathématique.

Quand les taux de cache importent (et sont prédictifs)

1) Charges majoritairement en lecture avec un working set stable

Si votre charge relit de façon répétée les mêmes blocs — démarrages massifs de VM, réutilisation d’artéfacts CI, distribution d’actifs web, analyses répétées sur un sous-ensemble « chaud » — alors le taux de hit ARC corrèle fortement avec la pression de lecture sur disque et la latence.

Dans ce cas, améliorer le taux de hit (plus de RAM, alignement recordsize, réduction du churn) est souvent un gain de performance direct.
On peut raisonner : moins de lectures disque → profondeur de file réduite → meilleure latence.

2) Charges dominées par les métadonnées

Lister des répertoires avec des millions d’entrées. Parcourir des arbres profonds. Construire des couches de conteneurs. Exécuter git sur de grands monorepos.
Ces charges bénéficient des hits de métadonnées dans l’ARC, même si les hits de données restent médiocres.

Ici, la métrique utile n’est pas le « taux de hit global », mais « est-ce que les misses de métadonnées provoquent des lectures aléatoires synchrones ? » Si oui, le dimensionnement de l’ARC et le placement des métadonnées (special vdev) peuvent être transformateurs.

3) Pools où les disques sont le goulot d’étranglement

Si votre pool est rotatif (HDD) ou vos SSD sont déjà fortement utilisés, les misses ARC font mal parce que le temps de service disque est votre facteur limitant.
Les taux de hit comptent quand l’alternative est lente.

4) Vous évaluez un investissement L2ARC ou special vdev

Les taux de hit seuls ne suffisent pas, mais ils font partie du modèle de coût :
si votre flux de misses ARC est majoritairement des lectures aléatoires et que votre working set dépasse légèrement la RAM, L2ARC peut aider.
Si les misses sont des lectures séquentielles, des sauvegardes ou du streaming, L2ARC est surtout une dépense coûteuse.

Blague #1 : L2ARC est comme un stagiaire avec un chariot élévateur — parfois brillant, parfois coûteux, toujours sous supervision.

5) Vous diagnosez une régression et les taux de hit ont changé

Si une mise à niveau, un changement de configuration ou une modification de propriété de dataset coïncide avec une variation nette des taux de hit, cela peut être un indice fort. Ce n’est pas une preuve.
C’est un signal « suivre la fumée ».

Quand les taux de cache n’importent pas (et vous induiront en erreur)

1) Charges majoritairement en écriture

ARC n’est pas un cache d’écriture au sens où on l’entend souvent en réunion. Oui, ZFS utilise de la mémoire pour les données sales et les transaction groups, et il met en cache des lectures qui suivent souvent des écritures. Mais si votre douleur est la latence d’écriture ou des tempêtes fsync, les taux de hit sont un spectacle parallèle.

Pour les écritures, l’histoire importante est : sync vs async, SLOG (si présent), latence du pool et comportement de txg. Un beau taux de hit ARC ne vous sauvera pas d’un pool saturé effectuant de petites écritures synchrones.

2) Lectures en streaming et scans en un seul passage

Sauvegardes, copies de gros fichiers, pipelines médias, retraitement de logs, scans analytiques à froid : ils lisent beaucoup une fois et passent à autre chose.
Un faible taux de hit est attendu et sain. Le prefetch de ZFS peut donner l’impression que le cache « fonctionne » (parce qu’il stage des blocs brièvement dans l’ARC),
mais cela ne change pas la physique : vous êtes fondamentalement limité par le débit.

3) Quand le goulot est le CPU ou la contention de verrous

Décompression, checksum, chiffrement, dedup, churn pathologique des métadonnées, ou application mono-threadée peuvent s’emberlificoter sur le CPU.
Dans ce cas, le taux de hit ARC peut être excellent alors que le système est toujours lent, parce que le temps est consommé au-dessus de la couche I/O.

4) Quand votre pool est déjà suffisamment rapide

Si vous êtes sur du NVMe moderne et que vos cibles de latence sont atteintes, vous pouvez tolérer des misses. « Plus de hits » devient un indicateur de vanité. Vous ne gagnez rien avec 99 % d’ARC hits si le service est déjà rapide et stable.

5) Quand le taux de hit est gonflé par la mauvaise chose

ARC peut sembler « incroyable » parce qu’il met en cache des données qui ne vous intéressent pas : prefetch séquentiel, blocs transitoires, ou données chauffées par un benchmark que vous avez lancé une fois. Pendant ce temps, votre vraie charge manque des métadonnées et souffre.

Si vous ne devez retenir qu’une règle : ne touchez pas aux réglages sur la base d’un seul ratio de hit agrégé. Décomposez : metadata vs data, demand vs prefetch,
latence vs débit, sync vs async. Sinon vous réglez selon vos sentiments.

ARC vs L2ARC : différences pratiques

ARC : le plus rapide, le plus simple, mais facile à mal utiliser

ARC vit en RAM. Il est extrêmement rapide et peut servir des lectures sans toucher aux disques. Mais ARC partage la RAM avec tout le reste :
applications, page cache (sur certaines plateformes), structures noyau et métadonnées ZFS.

Si l’ARC est trop petit par rapport à votre working set, vous thrasherez : beaucoup de misses, évictions fréquentes et pics de lectures disque.
Si l’ARC est trop grand, vous affamez les applications et l’OS. Cela peut ressembler à « le stockage est lent » alors qu’il s’agit de pression de reclaim.

L2ARC : parfois excellent, parfois un impôt

L2ARC peut être un gain quand :

  • Votre charge est majoritairement en lecture et réutilise des blocs.
  • Votre working set est plus grand que la RAM mais pas démesurément plus grand.
  • Votre pool est plus lent que votre périphérique de cache (pool HDD, ou SSD de pool déjà occupé).
  • Vous avez suffisamment de RAM pour contenir les en-têtes L2ARC sans vous noyer.

L2ARC peut être une perte quand :

  • Votre charge est principalement des lectures en streaming (churn du cache).
  • Votre périphérique de cache n’est pas constamment en faible latence sous charge d’écriture.
  • Vous êtes déjà contraint en mémoire.
  • Vous attendez qu’il accélère les écritures synchrones (ce n’est pas le cas).

Pourquoi les taux diffèrent entre ARC et L2ARC

Le taux de hit ARC mesure les requêtes servies depuis la RAM. Le taux de hit L2ARC mesure les requêtes servies depuis le périphérique de cache.
Un « bon » taux L2ARC dépend de ce que vous cherchez à accomplir :
parfois même 10–20 % de hits L2ARC peuvent être significatifs si ces hits évitent des lectures aléatoires coûteuses vers HDD.

Aussi : L2ARC se remplit de façon asynchrone et historiquement n’était pas persistant au redémarrage. Sur de nombreux systèmes OpenZFS modernes,
la persistance L2ARC existe, mais la réalité opérationnelle compte toujours : temps de chauffe, comportement d’éviction et usure du périphérique.

Faits intéressants et contexte historique

  • ARC fut une fonctionnalité phare du design ZFS de Sun : il a remplacé la séparation traditionnelle « buffer cache vs page cache » par un cache adaptatif unique.
  • L’idée des “ghost lists” dans ARC (se souvenir des blocs récemment évincés) vient de la recherche académique sur le caching et aide à éviter le thrashing.
  • L2ARC est arrivé plus tard quand le flash est devenu viable ; les premiers SSD étaient rapides mais fragiles, ce qui a conduit à un comportement d’écriture conservateur pour le cache.
  • Historiquement, L2ARC n’était pas persistant au redémarrage : les caches démarraient froids, ce qui importait pour les « lunes de grande affluence » du lundi matin.
  • Les stats ARC sont devenues une culture : les admins comparaient les taux de hit comme les joueurs comparent les FPS, même quand les graphiques de latence étaient le vrai enjeu.
  • Les special vdevs (métadonnées/petits blocs sur des périphériques rapides) ont changé la conversation sur le caching en rendant les « misses » moins douloureuses.
  • La compression a changé la géométrie du cache : ARC stocke souvent des blocs compressés, augmentant effectivement la capacité du cache par GiB de RAM.
  • Le comportement de prefetch a évolué : ce qui ressemblait à de la « pollution de cache » dans une version pouvait être un prefetch plus intelligent dans une autre.
  • La réputation de la dédup comme vorace en RAM est méritée : la table de dédup peut dominer les besoins mémoire et fausser tout ce que vous croyez savoir sur ARC.

Playbook de diagnostic rapide

L’objectif n’est pas d’admirer les métriques. L’objectif est d’identifier le goulot d’étranglement en moins de 15 minutes, choisir le test suivant, et éviter le tuning en mode cargo-cult.

Première étape : est-ce IOPS/latence ou débit ?

  • Si les utilisateurs se plaignent de « lenteurs soudaines » et de timeouts : suspectez la latence/les IOPS.
  • Si les transferts sont juste plus lents de bout en bout : suspectez des limites de débit, CPU, ou réseau.

Deuxième étape : lectures ou écritures, sync ou async ?

  • IOPS de lecture élevés + await disque élevé : le cache peut être important.
  • IOPS d’écriture élevés avec sync : SLOG/latence du pool comptent plus que les taux de hit ARC.
  • Écritures élevées avec gros blocs : regardez le débit des vdevs et la fragmentation.

Troisième étape : l’ARC est-il sous pression ou se comporte-t-il normalement ?

  • Taille ARC bloquée et évictions élevées : vous thrashez peut-être.
  • Taille ARC stable, misses stables, latence toujours mauvaise : le goulot est ailleurs.

Quatrième étape : le pool est-il saturé ou en mauvais état ?

  • Vérifiez zpool iostat -v pour déséquilibre vdev, files d’attente élevées et périphériques lents.
  • Vérifiez les erreurs, resilvering, scrub, ou un disque en fin de vie qui bride le vdev.

Cinquième étape : validez avec une expérience ciblée

  • Vider les caches ? En production c’est généralement une mauvaise idée, mais vous pouvez lancer un test de lecture contrôlé sur un dataset non critique.
  • Changer une seule propriété (par ex. primarycache=metadata sur un dataset de sauvegarde) et observer le comportement de l’ARC.
  • Utiliser fio ou des métriques applicatives pour confirmer une amélioration.

Tâches pratiques : commandes, sorties, décisions

Ce sont les vérifications de terrain que j’attends qu’un SRE exécute avant de proposer du matériel, et avant de toucher aux réglages avec une grande patience.
Chaque tâche inclut : commande, sortie d’exemple, ce que ça signifie, et la décision à prendre.

Task 1: Confirm pool health and ongoing maintenance work

cr0x@server:~$ sudo zpool status
  pool: tank
 state: ONLINE
  scan: scrub repaired 0B in 02:14:33 with 0 errors on Tue Dec 24 03:10:11 2025
config:

        NAME        STATE     READ WRITE CKSUM
        tank        ONLINE       0     0     0
          raidz2-0  ONLINE       0     0     0
            sda     ONLINE       0     0     0
            sdb     ONLINE       0     0     0
            sdc     ONLINE       0     0     0
            sdd     ONLINE       0     0     0

errors: No known data errors

Signification : Si vous êtes en train de resilver, scrub ou en état dégradé, la performance peut chuter indépendamment du taux de cache.

Décision : Si un scan tourne pendant les heures de pointe, replanifiez. Si le pool est dégradé, réparez le matériel d’abord ; ne « tentez pas d’ajuster l’ARC » pour compenser.

Task 2: Identify read vs write load and latency at the pool level

cr0x@server:~$ sudo zpool iostat -v tank 1 5
                              capacity     operations     bandwidth
pool                        alloc   free   read  write   read  write
--------------------------  -----  -----  -----  -----  -----  -----
tank                        4.22T  7.58T  1.20K  3.40K  140M  220M
  raidz2-0                  4.22T  7.58T  1.20K  3.40K  140M  220M
    sda                         -      -    280    860  35.0M  56.0M
    sdb                         -      -    300    820  34.5M  55.0M
    sdc                         -      -    310    870  36.0M  56.5M
    sdd                         -      -    320    850  34.5M  55.0M
--------------------------  -----  -----  -----  -----  -----  -----

Signification : Ceci montre la distribution par vdev et par disque. Un déséquilibre important suggère un disque lent ou du queueing.

Décision : Si un disque traîne, enquêtez-le. Si tout le vdev est saturé, le cache peut aider les lectures — mais seulement si les misses sont aléatoires et réutilisables.

Task 3: Check dataset properties that directly change caching behavior

cr0x@server:~$ zfs get -o name,property,value,source recordsize,primarycache,secondarycache,compression,sync tank/data
NAME       PROPERTY        VALUE     SOURCE
tank/data  recordsize      128K      local
tank/data  primarycache    all       default
tank/data  secondarycache  all       default
tank/data  compression     lz4       local
tank/data  sync            standard  default

Signification : primarycache/secondarycache décident de ce qui peut entrer dans ARC/L2ARC. recordsize affecte la forme des I/O et l’efficacité du cache.

Décision : Pour les datasets de sauvegarde/streaming, envisagez primarycache=metadata pour éviter la pollution du cache. Pour les BDs, évaluez recordsize et sync séparément.

Task 4: Inspect ARC size and target

cr0x@server:~$ arcstat 1 3
    time  read  miss  miss%  dmis  dm%  pmis  pm%  mmis  mm%  arcsz     c
12:01:01   22K  1.8K     8   980    4   740    3   120    1   64G   64G
12:01:02   21K  2.0K     9  1.1K    5   760    3   140    1   64G   64G
12:01:03   20K  1.9K     9  1.0K    5   780    4   120    1   64G   64G

Signification : arcsz est la taille courante de l’ARC ; c est la cible. Miss% sont les misses de demande. Les misses de prefetch sont séparés.

Décision : Si arcsz est bloqué à c et que les misses sont élevés avec une latence de lecture disque en hausse, vous êtes peut-être sous-cache. Si les misses sont faibles, le cache n’est pas votre goulot.

Task 5: Separate demand vs prefetch to detect cache pollution

cr0x@server:~$ arcstat -f time,read,miss,miss%,pmis,pm%,arcsz,c 1 3
    time  read  miss  miss%  pmis  pm%  arcsz     c
12:02:10   18K  2.2K    12   1.9K   10   64G   64G
12:02:11   19K  2.1K    11   1.8K   10   64G   64G
12:02:12   18K  2.3K    12   2.0K   11   64G   64G

Signification : Des misses de prefetch élevés (pm%) pendant des lectures en streaming sont normaux ; des hits de prefetch élevés peuvent évincer des données utiles.

Décision : Si un job de backup crée une énorme activité de prefetch et provoque des pics de latence interactifs, isolez-le (dataset séparé, limiter l’I/O, définir des propriétés de cache).

Task 6: Check L2ARC presence and effectiveness

cr0x@server:~$ arcstat -f time,l2read,l2miss,l2hit%,l2asize,l2size 1 3
    time  l2read  l2miss  l2hit%  l2asize  l2size
12:03:01     6K     4K      33     420G     800G
12:03:02     7K     5K      29     421G     800G
12:03:03     6K     4K      33     421G     800G

Signification : Le % de hit L2ARC peut sembler « moyen » et rester précieux s’il évite des lectures disque lentes. Surveillez aussi son niveau réel (l2asize).

Décision : Si L2ARC est à peine utilisé ou si le % de hit est faible et que vos misses sont en streaming, retirez-le ou réaffectez le périphérique. S’il aide les lectures aléatoires, conservez-le.

Task 7: Verify memory pressure before blaming ARC size

cr0x@server:~$ free -h
               total        used        free      shared  buff/cache   available
Mem:           256Gi       210Gi       3.1Gi       2.0Gi        43Gi        20Gi
Swap:           16Gi       9.5Gi       6.5Gi

Signification : Un faible « available » et une utilisation active du swap signifient une pression mémoire. L’ARC peut être en concurrence avec les applis.

Décision : Si swap est utilisé, corrigez la pression mémoire d’abord (réduire les charges, ajouter de la RAM, limiter l’ARC) avant de courir après les taux de hit.

Task 8: Measure disk latency directly on Linux

cr0x@server:~$ iostat -x 1 3
Device            r/s     w/s   r_await   w_await  aqu-sz  %util
sda             280.0   860.0     18.2     12.4    9.10   98.0
sdb             300.0   820.0     17.9     12.1    8.80   97.5
sdc             310.0   870.0     18.5     12.7    9.30   98.3
sdd             320.0   850.0     18.0     12.2    9.00   97.9

Signification : Un await élevé et un %util élevé indiquent une saturation/queueing du périphérique. Les hits de cache ne corrigeront pas des écritures saturées.

Décision : Si la latence est élevée à cause des écritures, examinez le comportement sync, le SLOG, et l’amplification d’écriture (recordsize, petits blocs, fragmentation).

Task 9: See if sync writes are dominating

cr0x@server:~$ zfs get -o name,property,value,source sync tank/db
NAME     PROPERTY  VALUE     SOURCE
tank/db  sync      standard  default

Signification : sync=standard signifie que l’application décide. Les bases de données font souvent beaucoup d’écritures synchrones.

Décision : Si la latence corrèle avec fsync, vous avez besoin d’un SLOG adapté (rapide, protégé en perte de puissance) ou d’un réglage applicatif — pas du tuning du taux de hit ARC.

Task 10: Confirm whether a SLOG exists and where

cr0x@server:~$ sudo zpool status tank | sed -n '1,80p'
  pool: tank
 state: ONLINE
config:

        NAME        STATE     READ WRITE CKSUM
        tank        ONLINE       0     0     0
          raidz2-0  ONLINE       0     0     0
            sda     ONLINE       0     0     0
            sdb     ONLINE       0     0     0
            sdc     ONLINE       0     0     0
            sdd     ONLINE       0     0     0
        logs
          nvme0n1   ONLINE       0     0     0

Signification : Un log vdev est votre SLOG. Sa latence et ses caractéristiques de durabilité comptent pour les écritures synchrones.

Décision : Si vous n’avez pas de SLOG et que la latence des écritures synchrones vous tue, envisagez d’en ajouter un. Si vous avez un SSD grand public comme SLOG, remplacez-le avant qu’il ne vous remplace votre week-end.

Task 11: Spot ARC eviction pressure (Linux /proc)

cr0x@server:~$ egrep 'c_max|c_min|size|memory_throttle_count|deleted|evict' /proc/spl/kstat/zfs/arcstats
c_max                           4    68719476736
c_min                           4    17179869184
size                            4    68719476736
memory_throttle_count           4    0
deleted                         4    119283
evict_skip                      4    0

Signification : size à c_max n’est pas mauvais en soi. Une augmentation de memory_throttle_count suggère que l’ARC est forcé de se réduire ou est throttlé.

Décision : Si le throttling augmente pendant la charge, cherchez une contention mémoire et envisagez de limiter l’ARC ou déplacer des charges.

Task 12: Understand metadata vs data behavior in ARC

cr0x@server:~$ egrep 'demand_data_hits|demand_data_misses|demand_metadata_hits|demand_metadata_misses' /proc/spl/kstat/zfs/arcstats
demand_data_hits                4    99887766
demand_data_misses              4    5544332
demand_metadata_hits            4    22334455
demand_metadata_misses          4    112233

Signification : Beaucoup de misses de données peuvent être acceptables pour le streaming. Les misses de métadonnées sont plus inquiétants pour les charges « l’UI est lente ».

Décision : Si les misses de métadonnées grimpent avec des pics de latence, envisagez un special vdev pour métadonnées ou augmentez l’ARC (si la mémoire le permet).

Task 13: Check whether a “special” vdev exists for metadata/small blocks

cr0x@server:~$ sudo zpool status tank | sed -n '1,140p'
  pool: tank
 state: ONLINE
config:

        NAME           STATE     READ WRITE CKSUM
        tank           ONLINE       0     0     0
          raidz2-0     ONLINE       0     0     0
            sda        ONLINE       0     0     0
            sdb        ONLINE       0     0     0
            sdc        ONLINE       0     0     0
            sdd        ONLINE       0     0     0
        special
          mirror-1     ONLINE       0     0     0
            nvme1n1    ONLINE       0     0     0
            nvme2n1    ONLINE       0     0     0

Signification : Un special vdev peut décharger les métadonnées et éventuellement les petits blocs sur des périphériques rapides, réduisant la douleur des misses de cache.

Décision : Si les misses de métadonnées vous font souffrir et que vous n’avez pas de special vdev, évaluez-en un. Si vous en avez un, vérifiez ces périphériques pour usure/latence.

Task 14: Identify dataset-level cache policy mismatches

cr0x@server:~$ zfs get -r -o name,property,value primarycache tank | head
NAME                 PROPERTY      VALUE
tank                 primarycache  all
tank/backups         primarycache  all
tank/backups/daily   primarycache  all
tank/db              primarycache  all
tank/home            primarycache  all

Signification : Les datasets de backup ont par défaut le caching de tout, ce qui peut évincer des données chaudes sans bénéfice.

Décision : Mettez les datasets de backup en primarycache=metadata (ou même none dans les cas extrêmes) et laissez les datasets interactifs tranquilles.

Task 15: Validate that recordsize matches workload reality

cr0x@server:~$ zfs get -o name,property,value recordsize tank/db tank/vm tank/backups
NAME         PROPERTY    VALUE
tank/db      recordsize  16K
tank/vm      recordsize  64K
tank/backups recordsize  1M

Signification : Les I/O DB aléatoires petites préfèrent un recordsize petit ; les backups aiment les gros. Un mauvais recordsize peut gaspiller l’ARC et causer une amplification read-modify-write.

Décision : Si le taux de hit est bas parce que vous mettez en cache des records géants pour de petites lectures, ajustez le recordsize sur le dataset (prudemment, pour les nouvelles écritures).

Task 16: Quick “is it the app?” sanity check with per-process I/O

cr0x@server:~$ sudo pidstat -d 1 3
Linux 6.8.0 (server)   12/25/2025  _x86_64_  (32 CPU)

12:05:10 PM   UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s  Command
12:05:11 PM  1001     24182   1200.00   9800.00      0.00  postgres
12:05:11 PM     0     19876      0.00  64000.00      0.00  zfs

Signification : Confirme qui génère l’I/O. Si un job de batch tape fort en écriture, les taux de hit de cache sont de simples spectateurs.

Décision : Si un voisin bruyant est responsable, bridez/le répartissez/déplacez le job avant de toucher aux tunables ZFS.

Trois mini-récits d’entreprise du terrain

Mini-récit 1 : L’incident causé par une mauvaise hypothèse

Une entreprise de taille moyenne exploitait une plateforme d’analytique multi-tenant. Pendant une semaine de lancement, les tableaux de bord ont ralenti et certaines requêtes ont expiré.
L’équipe stockage a vu le ratio de hit ARC chuter de la mi-90 % au bas des 70 %. La conclusion est venue instantanément : « Il nous faut plus de RAM. »

Ils ont acheté de la mémoire en urgence, programmé une fenêtre de maintenance, et ont en attendant essayé de « protéger le cache » en désactivant le prefetch et en changeant quelques
propriétés de dataset à travers le pool. Le lendemain, le système allait pire. Les pics de latence se sont accentués et les taux d’erreur internes ont augmenté.

Le vrai problème était les écritures synchrones. Une nouvelle voie d’ingestion utilisait une librairie qui fsyncait agressivement. Le pool n’avait pas de SLOG et les vdevs étaient déjà
près de la saturation en pointe. Les lectures souffraient parce que les écritures faisaient la queue ; le ratio ARC a baissé parce que le système était simplement plus lent à
servir les misses, pas parce que le cache « avait cassé ».

Une fois qu’ils ont tracé la latence des écritures sync, c’était évident. Ils ont ajouté un SLOG protégé contre la perte de puissance, corrigé le chemin d’ingestion, et annulé
les changements de tuning du cache. Le ratio ARC a récupéré un peu, mais surtout, les latences de queue ont retrouvé les SLO.

Leçon : une baisse du taux de hit peut être un effet, pas une cause. Les métriques de cache sont d’excellents témoins et de terribles suspects.

Mini-récit 2 : L’optimisation qui s’est retournée contre eux

Une autre organisation exploitait un cluster de VM sur ZFS. Quelqu’un a proposé L2ARC sur un NVMe grand public brillant : « On aura des performances comme la RAM sans acheter de RAM. »
Le changement est entré pendant une période calme. Les tests initiaux semblaient meilleurs. Tout le monde s’est détendu.

Deux semaines plus tard, le cluster a subi un nouveau pattern de charge : beaucoup de VM éphémères faisant des installations de paquets et des builds CI — beaucoup de lectures, oui, mais aussi un énorme churn.
L2ARC a commencé à se remplir de blocs jamais réutilisés. L’ARC a dû maintenir des métadonnées pour ces blocs mis en cache, et la pression mémoire a augmenté.
L’hyperviseur a commencé à swapper de façon intermittente. La latence est devenue étrange : pas constamment mauvaise, mais imprévisible au pire moment.

L’équipe a regardé le taux de hit L2ARC. Ce n’était pas brillant, mais ce n’était pas catastrophique non plus. Ils se sont disputés pour savoir si « 30 % » était « bien ».
Pendant ce temps, les clients ouvraient des tickets.

La solution a été péniblement ennuyeuse : retirer L2ARC, limiter l’ARC pour laisser de la marge à l’hyperviseur et aux invités, et isoler l’espace scratch CI sur un dataset
avec cache restreint aux métadonnées. Ils ont aussi déplacé les charges de build les plus bruyantes vers un pool différent.

Leçon : L2ARC n’est pas gratuit. Si votre charge churn beaucoup, vous payez une surcharge pour mettre en cache des données que vous ne reverrez jamais.

Mini-récit 3 : La pratique ennuyeuse mais correcte qui a sauvé la journée

Une équipe de services financiers utilisait ZFS pour des home directories et des outils internes. Rien de glamour ; beaucoup de petits fichiers, beaucoup de parcours de répertoires,
et des plaintes occasionnelles « pourquoi mon checkout de repo est lent ». Ils avaient une habitude : chaque trimestre, ils revoyaient les propriétés des datasets et validaient que
les datasets « bulk » (sauvegardes, exports, archives médias) n’étaient pas autorisés à inonder l’ARC.

Leur dataset de backups avait primarycache=metadata. Leur dataset d’archive avait un recordsize réglé large. Leurs datasets interactifs restaient en valeurs par défaut.
L’équipe suivait aussi la latence du pool et les misses de métadonnées ARC comme signaux de première classe.

Un jour, un nouveau job de backup a pointé par erreur le dataset interactif au lieu du dataset de backups. Il a commencé à lire en streaming pendant des heures en journée.
Sur la plupart des systèmes, cela aurait vidé l’ARC et déclenché une tempête de plaintes « le stockage est lent ».

Ici, le rayon d’impact a été limité. Le mauvais dataset était bruyant, mais le reste du pool est resté réactif. Le ratio ARC a chuté brièvement, mais les métadonnées sont
restées chaudes et la latence côté utilisateur n’a pas effondré. L’équipe a détecté la mauvaise configuration dans les logs du job et l’a corrigée sans incident majeur.

Leçon : une petite hygiène cohérente du cache bat le tuning héroïque. La meilleure panne est celle qui ressemble à une erreur d’arrondi.

Erreurs fréquentes (symptômes → cause racine → fix)

1) « Le ratio de hit ARC est bas, donc le stockage est lent »

Symptômes : Le taux de hit baisse lors de jobs batch ; les utilisateurs se plaignent ; quelqu’un propose de doubler la RAM.

Cause racine : Lectures en streaming ou scans ponctuels qui n’utilisent pas la réutilisation. Les misses sont attendus ; le débit est la contrainte.

Fix : Isolez les workloads batch (dataset/pool séparé), définissez primarycache=metadata sur les datasets bulk, bridez avec cgroups/ionice, et mesurez débit/latence directement.

2) « L2ARC résoudra notre latence d’écriture »

Symptômes : Latence fsync DB mauvaise ; l’équipe ajoute L2ARC ; rien n’améliore.

Cause racine : L2ARC accélère les lectures, pas les écritures sync. La latence d’écriture est gouvernée par le SLOG/pool.

Fix : Ajoutez un SLOG approprié pour les charges sync-heavy, ou changez le comportement dync de l’application (si sûr). N’achetez pas des SSD pour la mauvaise tâche.

3) Le taux de cache est élevé, mais l’appli est toujours lente

Symptômes : ARC hit > 95 %, les utilisateurs subissent des timeouts.

Cause racine : Saturation CPU (checksums/compression/chiffrement), contention de verrous, ou un dataset unique chaud provoquant des délais de txg.

Fix : Profilez le CPU, vérifiez iowait vs user time, inspectez txg et le comportement des écritures sync, et validez les goulots applicatifs.

4) « On mettra primarycache=none partout pour stopper la pollution »

Symptômes : Le taux de hit chute, les misses de métadonnées explosent, les opérations sur répertoires deviennent douloureuses.

Cause racine : Sur-correction : vous avez retiré la chose qui rend les workloads système de fichiers réactifs.

Fix : Utilisez primarycache=metadata uniquement pour les datasets bulk. Gardez all pour les datasets interactifs sauf raison précise.

5) L2ARC rend le système moins stable

Symptômes : Swap occasionnel, latence saccadée, pression de reclaim noyau.

Cause racine : Pas assez de RAM pour les en-têtes L2ARC et l’ARC ; le périphérique de cache encourage plus de churn.

Fix : Retirez ou réduisez L2ARC, limitez l’ARC, ou ajoutez de la RAM. Si vous exécutez des hyperviseurs, protégez d’abord la mémoire de l’hôte.

6) « On a désactivé le prefetch et ça a empiré »

Symptômes : Le débit de lecture séquentielle chute, les applis font plus de lectures synchrones.

Cause racine : Le prefetch aidait votre charge réelle ; vous avez supposé qu’il polluait parce que vous avez vu des stats de prefetch.

Fix : Réactivez le prefetch, et contrôlez plutôt les workloads qui causent du streaming nuisible. Mesurez avant/après.

7) « Notre ARC est énorme ; pourquoi manque-t-on sur les métadonnées ? »

Symptômes : Beaucoup de RAM, mais les misses de métadonnées augmentent lors de parcours de répertoires.

Cause racine : Le working set est vraiment énorme, ou le special vdev est absent et les métadonnées doivent être lues depuis des disques lents, rendant les misses douloureux.

Fix : Envisagez un special vdev pour métadonnées/petits blocs, réduisez le nombre de fichiers par répertoire, et assurez-vous que les datasets bulk n’évincèrent pas les métadonnées.

Blague #2 : Si votre seul outil est le taux de hit ARC, chaque problème de performance ressemble à « ajouter de la RAM ». Voilà comment on devient « la personne qui commande de la RAM ».

Listes de contrôle / plan étape par étape

Étape par étape : décider si les taux de cache sont actionnables

  1. Définissez la douleur : latence queue, débit, jitter ou timeouts ? Obtenez d’abord un graphique applicatif.
  2. Classifiez la charge : lecture-heavy, écriture-heavy, mixte ; streaming vs working set réutilisé.
  3. Vérifiez la santé du pool : zpool status pour degraded/resilver/scrub pendant la pointe.
  4. Vérifiez la latence des périphériques : zpool iostat -v et iostat -x. Si les disques sont saturés, les caches ne répareront pas les écritures.
  5. Vérifiez le comportement sync : identifiez les applis fsync-heavy ; vérifiez la configuration SLOG si nécessaire.
  6. Inspectez le comportement de l’ARC : demand vs prefetch misses ; metadata vs data misses ; compteurs d’éviction/throttle.
  7. Vérifiez la pression mémoire : swap ou faible mémoire disponible invalident le tuning simpliste de l’ARC.
  8. Décidez ensuite : ajouter de la RAM, ajuster les propriétés de cache des datasets, ajouter un special vdev, ajouter/retirer L2ARC, ou ne rien faire.

Checklist opérationnelle : éviter que les caches deviennent une superstition

  • Partitionnez les datasets par type de workload : interactif vs bulk vs DB vs VM.
  • Définissez primarycache=metadata sur les datasets bulk (backups, exports) sauf preuve du contraire.
  • Gardez compression=lz4 par défaut sauf si le CPU est vraiment votre goulot.
  • Revoyez recordsize pour DB/VM ; n’héritez pas d’un « 1M partout » parce que quelqu’un a lu un blog.
  • Suivez la latence au niveau pool et périphérique, pas seulement les taux de hit.
  • Documentez pourquoi chaque tunable existe ; retirez-le si personne ne peut l’expliquer.
  • Testez L2ARC avec des traces de workload réelles ; ne décidez pas uniquement sur des benchmarks synthétiques.
  • Protégez la marge mémoire sur les hyperviseurs et systèmes multi-tenant ; la gourmandise du cache est la façon d’invoquer le swap.

FAQ

1) Quel est un « bon » ratio de hit ARC ?

Il n’y a pas de nombre universel. Pour une charge stable majoritairement en lecture, un ratio plus élevé signifie généralement moins de lectures disque et une meilleure latence.
Pour les lectures en streaming, un faible ratio est normal et pas problématique. Jugez par la latence et l’utilisation disque, pas par l’esthétique.

2) Pourquoi le ratio ARC a-t-il baissé après avoir ajouté de la RAM ?

Parce que la charge a changé, parce que vous avez commencé à mesurer différemment, ou parce que le système fait maintenant plus de prefetch/lectures sous charge plus élevée.
Aussi, ajouter de la RAM peut augmenter la concurrence (les applis font plus de travail), ce qui change la dynamique du cache. Regardez les misses et la latence, pas seulement le ratio.

3) La compression améliore-t-elle les taux de cache ?

Souvent, oui — indirectement. Avec une compression comme lz4, l’ARC peut contenir plus de données logiques par GiB de RAM (selon l’implémentation et la charge).
Mais si le CPU est contraint, la compression peut échanger I/O contre CPU et nuire à la latence.

4) Dois-je mettre primarycache=metadata partout ?

Non. C’est une réaction fréquente excessive. Utilisez-la sur les datasets qui effectuent de grandes lectures en streaming (backups, archives) pour qu’ils n’évincèrent pas le cache utile.
Gardez les datasets interactifs sur all sauf preuve du contraire.

5) L2ARC vaut-il le coup sur des pools NVMe ?

Parfois, mais le seuil est plus élevé. Si votre pool est déjà NVMe à faible latence, L2ARC n’apportera peut-être pas grand-chose et peut ajouter une surcharge.
L2ARC brille quand il évite des misses coûteux — comme des lectures aléatoires vers HDD ou SSD occupés — surtout quand le working set dépasse légèrement la RAM.

6) L2ARC peut-il nuire aux performances ?

Oui. Il consomme de la RAM pour les en-têtes et peut augmenter la pression mémoire. Il peut aussi gaspiller la bande passante d’écriture du périphérique de cache en se remplissant de blocs non réutilisés.
Si vous voyez du swap ou une latence saccadée après l’avoir activé, prenez cela comme un signal sérieux.

7) Si mon taux L2ARC n’est que de 20 %, dois-je le retirer ?

Pas automatiquement. Demandez-vous : que remplacent ces 20 % de hits ? S’ils évitent des lectures aléatoires lentes vers HDD, 20 % peut être énorme.
S’ils remplacent des lectures déjà rapides ou sont surtout du prefetch, cela peut être inutile.

8) ARC aide-t-il les écritures ?

ARC est principalement un cache de lecture. ZFS met en mémoire les données dirty avant de committer les transaction groups, et les écritures peuvent être coalescées.
Mais si votre problème est la latence d’écritures synchrones, les taux de hit ARC ne sont pas le levier. Regardez le SLOG et la latence d’écriture du pool.

9) Pourquoi mes taux de hit semblent excellents mais les utilisateurs se plaignent encore ?

Parce que la latence peut provenir d’ailleurs : écritures synchrones, saturation CPU, problèmes réseau, verrous applicatifs, ou un seul périphérique lent dans un vdev.
Validez avec zpool iostat -v, iostat -x et les métriques applicatives.

10) Quel est le réglage le plus simple et sûr qui aide généralement ?

Isolez les datasets bulk et mettez primarycache=metadata dessus. Gardez compression=lz4. Vérifiez l’alignement du recordsize pour les datasets DB/VM.
Tout le reste doit être justifié par des mesures.

Conclusion : quoi faire ensuite

Les taux de cache ne sont pas la performance. Ce sont un indice. Parfois un très bon indice. Mais si vous les traitez comme un tableau de scores, vous règlerez la mauvaise chose et resterez lent — juste avec des graphiques plus jolis.

Étapes pratiques suivantes :

  1. Commencez à suivre la latence et l’utilisation pool/périphérique en parallèle des stats ARC/L2ARC.
  2. Séparez les datasets par workload et appliquez des politiques de cache délibérées (bulk vs interactif vs DB/VM).
  3. Utilisez le playbook de diagnostic rapide : santé → latence → comportement sync/écritures → décomposition ARC → ensuite seulement tuning du cache.
  4. Si vous changez quelque chose, changez une chose à la fois et validez avec des métriques applicatives, pas seulement les taux de hit.

Vous n’avez pas besoin de taux de hit parfaits. Vous avez besoin d’une latence prévisible, d’un débit stable, et d’un système qui ne vous surprend pas à 2 h du matin.
ZFS peut le faire — si vous cessez de faire du cache une religion.

← Précédent
Ubuntu 24.04 : disque « bloqué » sous charge — réglages de timeout qui évitent les blocages complets (cas n°90)
Suivant →
Problèmes MTU sur les réseaux Docker : pourquoi les grosses requêtes échouent et comment corriger MTU/MSS

Laisser un commentaire