29 points par xguru 2022-08-17 | 3 commentaires | Partager sur WhatsApp
  • Exploitation d’un cluster de base de données NoSQL (ScyllaDB) traitant 2 millions de messages par seconde
  • Le facteur qui affecte le plus les performances de la base est la latence du matériel de disque physique
    → À faible volume de requêtes, cela importe peu, mais au-delà d’un certain seuil, des temps de lecture de seulement 1 à 2 ms suffisent à créer une file d’attente des lectures sur disque et à provoquer des timeouts sur les requêtes elles-mêmes
  • La latence disque se mesure généralement en microsecondes, alors pourquoi une opération disque prend-elle 1 à 2 ms ?
  • Discord exploite la majeure partie de son matériel sur Google Cloud
    • Le cloud prend en charge les SSD locaux basés sur NVMe, mais leurs propres tests ont révélé des problèmes de fiabilité, ce qui ne les rendait pas rassurants pour stocker des données critiques
    • Les Persistent Disk peuvent être attachés/détachés à chaud d’un serveur, redimensionnés sans interruption, permettent de créer des snapshots à tout moment et sont conçus pour être répliqués par défaut
      → Le problème, c’est qu’ils ne sont pas directement connectés au serveur, mais reliés via le réseau
  • Même avec une très faible latence de connexion sur le réseau local, on ne descend pas en dessous de PCI/SATA
    → Réseau : 1 à 2 ms, disque directement connecté : 0,5 ms
  • Avec un SSD local, si un problème matériel survient comme sur un HDD, on perd les données de ce disque, et si c’est l’hôte lui-même qui a un problème, il devient même impossible de faire un snapshot, ce qui peut mener à une perte totale des données
    → C’est pourquoi Discord n’utilise pas de Local SSD, mais des Persistent Disk

Analyse du problème

  • L’idéal serait d’avoir un stockage réunissant les avantages du SSD local et du Persistent Disk, mais cela n’existe pas. Et si on n’en reprenait qu’une partie ?
  • Chez Discord, la latence en écriture n’est pas le problème. Ce qui affecte les performances, c’est la « latence de lecture »
  • Le « redimensionnement de disque sans interruption » n’est pas une fonction indispensable. La taille peut être anticipée à l’avance
  • Les exigences finales sont les suivantes
    • Rester sur GCP
    • Utiliser des snapshots Point-in-Time pour la sauvegarde des données
    • Faire de la minimisation de la latence de lecture la priorité absolue
    • Ne pas sacrifier la garantie d’uptime de la base existante
  • L’idée serait donc d’utiliser les Local SSD de GCP pour la lecture et les Persistent Disk pour l’écriture
    → Peut-on créer un tel super-disque au niveau logiciel ?

Construire un Super-Disk

  • L’exigence correspondait essentiellement à un cache en write-through. Utiliser les Local SSD de GCP comme cache et les PD comme couche de stockage
  • Les serveurs de base utilisaient Ubunut, donc il était possible d’appliquer un cache au niveau disque dans le noyau Linux (avec des modules comme dm-cache, lvm-cache, bcache)
  • Mais les expérimentations ont montré qu’en cas de secteur défectueux sur le disque de cache, l’ensemble des lectures échouait
    • En cas de bad sector, il aurait fallu relire la donnée depuis la couche de stockage et la réécrire par-dessus, mais aucune des solutions de cache disque évaluées n’offrait cette fonction
    • Lorsqu’un bad sector apparaissait, la base de données s’arrêtait pour des raisons d’intégrité des données
  • Une exigence supplémentaire a donc été ajoutée : « survivre même si un bad sector survient sur le Local SSD »
  • Ils se sont donc tournés vers md dans le noyau Linux
    • md permet de créer du RAID logiciel
    • Mettre le SSD et le PD en miroir ne résolvait pas le problème, car plus de la moitié des lectures se feraient depuis le PD
    • md dispose d’une option write-mostly absente du RAID traditionnel
      • Lorsqu’un disque est marqué write-mostly, il est exclu des lectures normales et n’est lu qu’en l’absence d’autre option. « Utile pour les périphériques connectés lentement »
      • En d’autres termes, en groupant le SSD et le PD en RAID1 puis en configurant le PD en write-mostly, il devenait possible de satisfaire les exigences
  • Le dernier problème restant était que les Local SSD de GCP ont une capacité fixe de 375 Go
  • Pour certaines applications, Discord a besoin de plus de 1 To par instance de base de données
  • Ils ont donc décidé d’agréger plusieurs SSD en RAID0
  • Le schéma final est le suivant
    • 4 Local SSD agrégés en RAID0 constituent md0
    • md0 et le Persistent Disk sont ensuite assemblés en RAID1 dans md1

Performances de la base

  • Le résultat a été exactement celui attendu
  • Même aux pics de charge, les opérations disque ne s’accumulent pas dans la file d’attente et la latence des requêtes ne varie pas
  • Les performances se sont améliorées, ce qui a permis d’augmenter encore le volume de requêtes traité par chaque serveur
  • Ceux qui ont déjà utilisé du RAID se demanderont sans doute : « est-ce que ça peut vraiment simplement fonctionner ? », mais en pratique il s’est passé toutes sortes de choses, et le reste sera présenté plus en détail séparément

3 commentaires

 
eajrezz 2022-08-19

Autrefois, ils n’étaient pas satisfaits des performances de golang au point d’écrire même des serveurs en rust, et je trouve que cela montre à quel point l’esprit geek de l’entreprise Discord est impressionnant.

 
psyrenpark 2022-08-17

J’ai l’impression qu’ils utilisent un marteau-piqueur pour résoudre un problème qu’on aurait pu régler avec une houe.

 
xguru 2022-08-17

Sur HN, certains disent aussi que ce n’est pas simplement un problème de GCP ?
https://news.ycombinator.com/item?id=32474093
Mais je pense que c’est utile au moins de savoir que ce genre de tentative est possible.