Tulip : Moderniser la plateforme de données de Meta
Les migrations sont difficiles. De plus, ils deviennent beaucoup plus difficiles chez Meta à cause de :
Avant d'entrer dans les détails de l'histoire de la migration, nous aimerions prendre du recul et essayer d'expliquer la motivation et la justification de cette migration.
Au fil du temps, la plateforme de données s’est transformée sous diverses formes à mesure que les besoins de l’entreprise augmentaient. Ce qui n’était au début qu’une modeste plate-forme de données est devenue une plate-forme à l’échelle de l’exaoctet. Certains systèmes desservant une plus petite échelle ont commencé à montrer des signes d'insuffisance face aux demandes croissantes qui leur étaient imposées. Plus particulièrement, nous avons rencontré des problèmes concrets de fiabilité et d'efficacité liés à la (dé)sérialisation des données, ce qui nous a amenés à repenser la façon dont nous enregistrons les données et à revoir les idées des principes premiers pour résoudre ces problèmes urgents.
Logger est au cœur de la plateforme de données. Le système est utilisé pour enregistrer les données analytiques et opérationnelles dans les pipelines de traitement Scuba, Hive et Stream via Scribe. Chaque équipe produit et plateforme de données interagit avec la journalisation. Le format des données pour la journalisation était soit Hive Text Delimited, soit JSON, pour des raisons héritées. Les limitations de ces formats sont décrites dans notre précédent article sur Tulip.
Pour remédier à ces limitations, le format de sérialisation Tulip a été développé pour remplacer les anciens formats de sérialisation spécifiques à la destination.
Les graphiques ci-dessous représentent graphiquement le parcours de migration pour la conversion du format de sérialisation vers Tulip afin de montrer la progression à différentes étapes et jalons.
Nous pouvons constater que même si le nombre de schémas de journalisation est resté à peu près le même (ou a connu une certaine croissance organique), les octets enregistrés ont connu une diminution significative en raison du changement de format de sérialisation. Les détails liés aux économies d'octets spécifiques au format sont présentés dans la section ci-dessous.
Remarque : Les chiffres du graphique 2 sont extrapolés (au trafic global) sur la base des économies réelles observées pour les cinq schémas de journalisation les plus importants (en volume).
Nous aimerions présenter notre parcours migratoire comme deux phases distinctes avec leurs propres perspectives.
Concevoir le système en tenant compte de la migration contribue à rendre la migration beaucoup plus facile. Les solutions d'ingénierie suivantes ont été développées pour garantir que l'équipe dispose des outils et du support d'infrastructure nécessaires pour changer de format filaire en toute sécurité et pour déboguer les problèmes pouvant survenir pendant la phase de migration de manière évolutive.
Les solutions se répartissaient en gros dans les catégories suivantes :
Défi : Comment faciliter la migration et réduire les risques en n'obligeant pas le(s) producteur(s) et consommateur(s) de données à changer de format de sérialisation de manière atomique ?
Solution : lors du basculement d'un schéma de journalisation unique pour utiliser le nouveau protocole de sérialisation Tulip pour écrire des charges utiles, la prise en charge des charges utiles en mode mixte sur un seul flux de scribe était nécessaire car il serait impossible de basculer « atomiquement » tous les producteurs de données pour utiliser le nouveau format. . Cela a également permis à l'équipe de limiter le déploiement du nouveau format de sérialisation.
Le format filaire en mode mixte était important pour prendre en charge le concept des enregistreurs fantômes, qui étaient largement utilisés pour les tests d'acceptation de bout en bout avant un déploiement à grande échelle.
Le principal défi du format filaire en mode mixte était de ne pas pouvoir modifier la sérialisation existante des charges utiles au format Hive Text ou JSON. Pour contourner cette limitation, chaque charge utile sérialisée Tulip est préfixée par la séquence de 2 octets 0x80 0x00, qui est une séquence utf-8 non valide.
Défi : Dans certains systèmes, le format de sérialisation Hive Text (ou JSON) s'est infiltré dans le code de l'application qui a fini par s'appuyer sur ce format pour consommer les charges utiles. Ceci est le résultat du fait que les consommateurs ont dépassé l’abstraction du format de sérialisation.
Solution : deux solutions ont permis de relever ce défi.
Lecteur (équivalent enregistreur pour la désérialisation des données)
Reader est une bibliothèque qui convertit une charge utile sérialisée en un objet structuré. Reader (comme logger) est disponible en deux versions, (a) code généré et (b) générique. Un objet lecteur consomme des données dans l'un des trois formats — Tulip, Hive Text ou JSON — et produit un objet structuré. Cela a permis à l'équipe de basculer les consommateurs vers les lecteurs avant le début de la migration. Le code de l'application a dû être mis à jour pour consommer cet objet structuré au lieu d'une ligne sérialisée brute. Cela a éloigné le format filaire des consommateurs de données.