Aller au contenu principal

Mémoire et éviction

Clustron Zaris est un store en mémoire : chaque nœud détient ses données en RAM, et chaque nœud est plafonné par un plafond mémoire. Cet article explique comment fonctionne ce plafond, ce qui se passe à mesure qu'un nœud se remplit, et comment l'éviction maintient un nœud dans sa limite.

Le store est un buffer borné​

Un nœud Zaris ne croît pas sans limite. Chaque nœud comptabilise en permanence la taille des données qu'il possède activement et maintient ce total sous un plafond configuré. La comptabilisation n'est jamais optionnelle — un nœud est toujours un buffer borné, et les seules choses que vous configurez sont la taille du plafond et ce que le nœud fait lorsqu'il l'atteint.

Le plafond par défaut est de 1 Gio de données activement possédées par nœud. Il n'existe délibérément aucun réglage « illimité » : si vous ne définissez pas de plafond, la valeur par défaut s'applique.

remarque

Le plafond couvre les données qu'un nœud possède activement — les copies primaires qu'il sert. Les copies de réplica qu'un nœud détient pour d'autres partitions sont suivies séparément et ne sont pas ce que le plafond du propriétaire actif prend en compte.

Ce qui se passe à mesure qu'un nœud se remplit​

Un nœud maintient son plafond de l'une de deux manières, selon que l'éviction est activée ou non :

ModeComportement au plafondRésultat d'une écriture qui le dépasserait
Éviction activée (par défaut)Le nœud évince les données plus anciennes pour faire de la placeL'écriture est admise ; d'autres données sont évincées
Éviction désactivéeLe nœud refuse les nouvelles donnéesL'écriture est rejetée avec KvStatus.CapacityExceeded

Un nœud Zaris se comporte comme un cache borné : sous pression mémoire, il évince pour rester dans le plafond, de sorte que les écritures continuent de réussir et que les données les moins précieuses sont supprimées en premier. L'alternative — un store qui rejette à la capacité et refuse les nouvelles écritures plutôt que de supprimer les données plus anciennes — est le mode sans éviction décrit ci-dessous.

remarque

Dans la version actuelle, un nœud s'exécute toujours avec l'éviction activée en utilisant la politique LRU. Le mode sans éviction et les politiques LFU / sensibles au TTL existent dans le moteur mais ne sont pas encore sélectionnables via la configuration — le plafond mémoire (memory.maxSizeBytes) est le réglage que vous contrôlez.

Politiques d'éviction​

Lorsque l'éviction est activée, une politique décide quels éléments supprimer en premier. Dans la version actuelle, la politique est toujours LRU — les autres politiques ci-dessous décrivent le modèle mais ne sont pas encore sélectionnables via la configuration. Zaris échantillonne un petit ensemble de candidats et évince ceux au score le plus bas, plutôt que de maintenir un ordre global strict — la même approche échantillonnée qu'utilise Redis.

PolitiqueÉvince en premierÀ utiliser quand
LRU (par défaut)Les éléments accédés le moins récemmentL'accès est biaisé par la récence — les données récentes sont susceptibles d'être relues
LFULes éléments accédés le moins fréquemmentUn ensemble chaud stable gagne à être conservé plutôt que les pics ponctuels
Sensible au TTLLes éléments les plus proches de leur expiration TTLLa plupart des données ont déjà un TTL et vous voulez un ordre d'expiration naturel
Sans évictionRien — le nœud rejette à la capacité à la placeVous ne voulez jamais que des données soient supprimées implicitement

La récence et la fréquence sont suivies comme des signaux approximatifs, en place, estampillés sur le chemin de lecture, de sorte qu'ils ne coûtent presque rien à maintenir et ne nécessitent jamais d'index séparé.

Comment fonctionne une passe d'éviction​

L'éviction est pilotée par une boucle d'arrière-plan, non par chaque écriture individuelle. La boucle utilise une hystérésis — un seuil de déclenchement haut et une cible plus basse — de sorte qu'elle ne se déclenche pas en continu au bord du plafond :

  • Déclenchement : une passe démarre lorsque l'utilisation active s'élève au-dessus de 80 % du plafond.
  • Cible : une fois déclenchée, la passe se poursuit jusqu'à ce qu'environ 30 % du plafond soit de nouveau libre — c'est-à-dire jusqu'à ce que l'utilisation retombe à environ 70 %.
  • Cadence : la boucle se réveille à un intervalle fixe (une seconde par défaut) et échantillonne un ensemble borné d'éléments candidats à chaque cycle.

Comme la cible post-éviction (70 %) se situe strictement en dessous du déclenchement (80 %), une passe ramène l'utilisation dans une bande calme au lieu de s'arrêter juste au point qui la redéclencherait immédiatement.

La limite de taille par élément​

Indépendamment du plafond global, un seul élément ne peut pas dépasser une taille maximale d'élément — 4 Mio par défaut. Cette limite est vérifiée à chaque écriture quel que soit le mode d'éviction : une valeur surdimensionnée n'est jamais admise, et aucune éviction ne fera de la place pour elle. Une écriture qui dépasse la limite est rejetée avec KvStatus.ItemTooLarge.

Cela protège un nœud d'une unique valeur pathologique et garde la comptabilisation par élément peu coûteuse.

Gérer les signaux de capacité dans votre code​

Les deux issues de capacité se manifestent sous forme de statuts typés sur le résultat que vous inspectez déjà — ce ne sont pas des exceptions, et ils sont distincts afin que vous puissiez réagir correctement à chacun :

var result = await client.PutAsync("report:2026-07", payload);

if (!result.IsSuccess)
{
switch (result.Status)
{
case KvStatus.ItemTooLarge:
// The value itself is too big — split it or store a reference instead.
break;
case KvStatus.CapacityExceeded:
// The node is full and eviction is disabled — retry later or shed load.
break;
}
}

CapacityExceeded ne survient qu'en mode sans éviction, qui n'est pas sélectionnable dans la version actuelle, de sorte que vous ne le rencontrerez normalement pas — un nœud plein évince sous la politique LRU toujours active plutôt que de rejeter. ItemTooLarge, en revanche, est une issue bien réelle et atteignable, et peut survenir dans n'importe quel mode.

Configuration​

Le plafond mémoire du nœud fait partie de la configuration du store, sous la section memory :

{
"memory": {
"maxSizeBytes": 2147483648
}
}

Définir maxSizeBytes à null (ou l'omettre) applique la valeur par défaut de 1 Gio. Dans la version actuelle, maxSizeBytes est le seul réglage mémoire configurable : la politique d'éviction (LRU), les seuils de déclenchement/cible et la limite par élément décrits ci-dessus sont des valeurs par défaut fixes, pas des réglages de configuration. Consultez la référence de configuration pour le schéma mémoire complet.

Ce que cela signifie pour la planification de capacité​

Comme chaque nœud est un buffer borné, la capacité totale d'un store est à peu près le plafond par nœud multiplié par le nombre de partitions qu'un nœud possède, ajusté pour le facteur de réplication (les réplicas détiennent des copies supplémentaires). Un nœud exécute aujourd'hui le cache LRU toujours actif, donc dimensionnez le plafond à votre working set plus une marge pour la bande d'éviction ; les données froides sont supprimées sous pression plutôt que rejetées.

Étapes suivantes​