Sujet : distributed-systems
-
Le traçage distribué en bref : spans, identifiants parents et W3C Trace Context
Une trace est un arbre de spans, chacun avec un identifiant de trace, son propre identifiant de span, un identifiant de span parent, des horodatages, des attributs et un statut ; l'en-tête W3C traceparent transporte l'identifiant de trace, l'identifiant parent et un indicateur sampled au-delà des frontières de processus, et un service qui se contente de retransmettre les deux en-têtes garde malgré tout les traces cohérentes.
-
Ce que garantit un cluster Raft : majorités, un seul leader et lectures linéarisables
Les systèmes de consensus tels qu'etcd (Raft) permettent à une majorité de serveurs de s'accorder sur un journal ordonné ; ils restent corrects quel que soit le nombre de pannes, mais ne progressent que tant qu'une majorité reste joignable. Les lectures linéarisables passent par le consensus et coûtent en latence ; les lectures sérialisables sont servies localement et peuvent être obsolètes.
-
Concevoir des opérations idempotentes et des nouvelles tentatives sûres
Une opération est idempotente lorsque son exécution répétée produit le même effet qu'une exécution unique ; la RFC 9110 fixe cela pour les méthodes HTTP, et un en-tête de clé d'idempotence transpose cette propriété à POST. Stocker la clé avec une empreinte et le résultat, signaler les conflits par 409 et 422, supprimer les clés après un délai documenté.
-
Les sagas : des workflows multi-étapes entre services, avec compensation au lieu d'un rollback
Une saga est une séquence de transactions locales réparties dans différents services, chacune déclenchant la suivante ; si une étape échoue, les étapes précédentes sont défaites par des transactions de compensation que la personne qui développe écrit. Les sagas rétablissent la cohérence sans transactions distribuées, mais renoncent à l'isolation : les états intermédiaires sont visibles, et les compensations doivent être conçues, pas supposées.
-
Amplification de la latence de queue : quand une requête attend la plus lente d'une centaine
Une requête qui se ramifie vers N backends est aussi lente que la plus lente des réponses, si bien qu'une réponse lente sur 100 par backend rend environ 63 % des requêtes à cent branches lentes. Le p99 de la feuille devient la médiane de la racine ; les remèdes sont moins de feuilles, des requêtes hedgées ou liées après un délai fondé sur un percentile, des délais limites avec résultats partiels, et l'élimination des causes des queues de latence des feuilles.
-
Publier des événements de façon fiable avec un outbox transactionnel
Écrire l'événement dans une table outbox au sein de la même transaction de base de données que le changement d'état, puis laisser un relais distinct le publier vers le broker. Cela supprime la fenêtre pendant laquelle l'état est enregistré mais l'événement est perdu (ou l'inverse), au prix d'une livraison au moins une fois et d'un relais à exploiter.
-
Des cloisons (bulkheads) par dépendance maintiennent la disponibilité des points de terminaison non liés lorsqu'une dépendance ralentit
Hypothèse : lorsqu'un service appelle plusieurs dépendances à partir d'un même bassin partagé de threads ou d'emplacements de concurrence, une dépendance qui devient lente (sans être hors service) entraîne avec elle des points de terminaison sans rapport dès que ce bassin est épuisé ; donner à chaque dépendance son propre bassin borné maintient les autres points de terminaison proches de leur latence et de leur taux d'erreur de référence pendant le même ralentissement.
-
Répliques en lecture et retard de réplication : à quoi ressemblent les lectures obsolètes et comment les borner
Une réplique en flux (streaming replica) applique le journal du primaire avec un certain délai, si bien qu'une lecture effectuée juste après une écriture peut ne pas voir cette écriture. Il faut orienter les lectures selon le niveau d'obsolescence toléré par chaque appelant, n'utiliser les modes de réplication synchrone que là où leur latence est acceptable, et comprendre que le rejeu du journal peut annuler des requêtes longues sur la réplique.
-
Les bases de gRPC : contrats protobuf, streaming et cas d'usage
gRPC appelle des méthodes définies dans un fichier .proto, Protocol Buffers servant à la fois de langage de définition d'interface et de format de transport ; il offre des appels unaires et en flux (streaming), des échéances (deadlines), des métadonnées et un ensemble fixe de codes de statut, le tout sur HTTP/2. Il convient aux communications de service à service et aux backends mobiles ; les navigateurs ont besoin de gRPC-Web, et les intégrateurs publics attendent généralement du JSON sur HTTP.
-
Hachage cohérent : un placement de clés stable quand les nœuds vont et viennent
Hacher une clé modulo le nombre de nœuds redistribue la plupart des clés dès qu'un nœud est ajouté ou retiré. Le hachage cohérent place les nœuds et les clés sur un anneau, de sorte que seules les clés voisines du nœud modifié se déplacent ; les nœuds virtuels égalisent la charge, et des variantes fondées sur des tables, comme Maglev, échangent un peu de stabilité de placement contre une recherche plus rapide.
-
Le traçage distribué en bref : spans, ID parent et propagation du contexte de trace W3C
Une trace est un arbre de spans, chacun doté d'un ID de trace, de son propre ID de span, d'un ID de span parent, d'horodatages, d'attributs et d'un statut ; l'en-tête W3C traceparent transporte l'ID de trace, l'ID parent et un indicateur sampled au-delà des frontières de processus, et un service qui se contente de transmettre les deux en-têtes conserve tout de même l'intégrité des traces.
-
CAP et PACELC comme aides à la décision plutôt que comme slogans
CAP n'interdit qu'un seul coin de l'espace de conception : une disponibilité parfaite et une cohérence linéarisable pendant la durée d'une partition réseau. PACELC ajoute l'arbitrage quotidien entre latence et cohérence en l'absence de partition. Utilisés comme des questions plutôt que comme des étiquettes, les deux aident à décider, opération par opération, où un système peut renvoyer des données obsolètes et où il doit se coordonner.
-
Contre-pression et files d'attente bornées : laisser l'étape la plus lente donner le rythme
Une file d'attente non bornée transforme une surcharge en épuisement de mémoire et en latence non bornée. La contre-pression signifie que le consommateur indique au producteur ce qu'il peut absorber, de la demande de Reactive Streams jusqu'au write() de Node.js qui renvoie false ; une file d'attente bornée assortie d'un comportement défini lorsqu'elle est pleine constitue le minimum requis pour chaque étape d'un service.
-
Sur quel signal de surcharge un petit service doit-il délester : attente en file, requêtes en cours ou CPU ?
Question ouverte : les recommandations citent le CPU, la latence, la longueur de la file et le nombre de threads comme déclencheurs possibles du délestage de charge, en indiquant que le choix dépend du service. Pour un service à quelques instances et sans système de quotas global, quel signal, quel seuil et quelle règle de priorité les équipes ont-elles réellement conservés en production, et comment les ont-elles réglés ?
-
Verrous distribués et baux de leader : expiration, jetons de barrière et ce qu'un verrou ne peut pas promettre
Un verrou distribué est un bail qui expire ; un processus mis en pause par un ramasse-miettes, une contention CPU ou un réseau retardé peut continuer d'agir après que son bail est passé à quelqu'un d'autre. Seul un jeton de barrière strictement croissant, vérifié par la ressource protégée, rend un tel verrou sûr pour la correction ; un verrou utilisé simplement pour éviter un travail en double demande moins.
-
Horloges logiques : horodatages de Lamport, horloges vectorielles et horloges hybrides
Les horloges murales de machines différentes ne concordent pas, si bien qu'ordonner des événements par horodatage fait perdre des mises à jour. Les horodatages de Lamport donnent un ordre compatible avec la causalité, les horloges vectorielles détectent en plus les mises à jour concurrentes, et les horloges logiques hybrides conservent une valeur proche de l'heure murale tout en préservant l'ordre causal.
-
Disjoncteurs (circuit breakers) : échouer rapidement quand une dépendance est en panne ou lente
Un disjoncteur compte les échecs et les appels lents vers une dépendance ; au-delà d'un seuil, il s'ouvre et rejette immédiatement les appels, puis laisse passer quelques appels d'essai (état semi-ouvert) avant de se refermer. Il protège les threads de l'appelant et laisse à la dépendance de la place pour se rétablir, mais seulement avec des fenêtres bien choisies, un repli (fallback) et un délai d'expiration sous-jacent.
-
Livraison au plus une fois, au moins une fois et exactement une fois
Les systèmes de messagerie livrent un message au plus une fois (avec risque de perte), au moins une fois (avec risque de duplication), ou de façon effectivement exacte une fois (dédupliqué par le consommateur) ; la combinaison au moins une fois plus des consommateurs idempotents constitue le choix par défaut en pratique, et « exactement une fois » est une propriété de l'ensemble du pipeline, pas du courtier de messages (broker).
-
Pipelines de suppression à travers les services, les magasins dérivés et les sauvegardes
Modéliser la suppression des données d'une personne comme une tâche avec un état par magasin dans la cartographie des données : diffuser un événement, exiger que chaque service propriétaire signale son achèvement avec des décomptes, traiter explicitement le stockage d'objets versionné et les magasins dérivés, borner la durée pendant laquelle les sauvegardes conservent les données ou détruire les clés par sujet, et conserver une liste de suppression afin que les restaurations puissent re-supprimer.
Lisible par machine : JSON