Dans le blog précédent, nous avons présenté les cas d'utilisation de Presto d'Uber et comment nous avons collaboré pour implémenter le cache local Alluxio afin de surmonter différents défis dans l'accélération des requêtes Presto. La deuxième partie traite des améliorations apportées aux métadonnées du cache local.
Tout d'abord, nous voulons empêcher la mise en cache obsolète. Les fichiers de données sous-jacents peuvent être modifiés par les frameworks tiers. Notez que cette situation peut être rare dans les tables Hive mais très courante dans les tables Hudi.
Deuxièmement, les lectures quotidiennes de données non dupliquées à partir de HDFS peuvent être importantes, mais nous n'avons pas assez d'espace de cache pour mettre en cache toutes les données. Par conséquent, nous pouvons introduire une gestion des quotas délimités en définissant un quota pour chaque table.
Troisièmement, les métadonnées doivent pouvoir être récupérées après le redémarrage du serveur. Nous avons stocké les métadonnées dans le cache local en mémoire au lieu du disque, ce qui rend impossible la récupération des métadonnées lorsque le serveur est arrêté et redémarré.
Par conséquent, nous proposons les métadonnées au niveau du fichier, qui contiennent et conservent l'heure de la dernière modification et la portée de chaque fichier de données que nous avons mis en cache. Le magasin de métadonnées au niveau du fichier doit être persistant sur le disque afin que les données ne disparaissent pas après le redémarrage.
Avec l'introduction des métadonnées au niveau des fichiers, il y aura plusieurs versions des données. Un nouvel horodatage est généré lors de la mise à jour des données, correspondant à une nouvelle version. Un nouveau dossier stockant la nouvelle page est créé correspondant à ce nouvel horodatage. En même temps, nous essaierons de supprimer l'ancien horodatage.
Comme indiqué ci-dessus, nous avons deux dossiers correspondant à deux horodatages : timestamp1 et timestamp2. Habituellement, lorsque le système est en cours d'exécution, il n'y aura pas deux horodatages simultanément car nous supprimerons l'ancien horodatage1 et ne conserverons que l'horodatage2. Cependant, dans le cas d'un serveur occupé ou d'une forte simultanéité, nous ne pourrons peut-être pas supprimer l'horodatage à temps, auquel cas nous pouvons avoir deux horodatages en même temps. De plus, nous maintenons un fichier de métadonnées qui contient les informations du fichier au format protobuf et le dernier horodatage. Cela garantit que le cache local d'Alluxio ne lit que les données du dernier horodatage. Lorsque le serveur redémarre, les informations d'horodatage sont lues à partir du fichier de métadonnées afin que le quota et l'heure de la dernière modification puissent être gérés correctement.
Étant donné qu'Alluxio est une solution de mise en cache générique, il a toujours besoin du moteur de calcul, comme Presto, pour transmettre les métadonnées à Alluxio. Par conséquent, sur le site Presto, nous utilisons le HiveFileContext. Pour chaque fichier de données de la table Hive ou de la table Hudi, Presto crée un HiveFileContext. Alluxio utilise ces informations lors de l'ouverture d'un fichier Presto.
Lors de l'appel de openFile, Alluxio crée une nouvelle instance de PrestoCacheContext, qui contient le HiveFileContext et a la portée (quatre niveaux : base de données, schéma, table, partition), quota, identifiant de cache (c'est-à-dire la valeur md5 du chemin du fichier), et les autres informations. Nous transmettrons ce contexte de cache au système de fichiers local. Alluxio peut ainsi gérer les métadonnées et collecter des métriques.
En plus de transmettre des données de Presto à Alluxio, nous pouvons également rappeler à Presto. Lors de l'exécution d'opérations de requête, nous connaîtrons certaines métriques internes, telles que le nombre d'octets de données lus dans le cache et le nombre d'octets de données lus à partir du stockage HDFS externe.
Comme indiqué ci-dessous, nous transmettons le HiveFileContext contenant le PrestoCacheContext au système de fichiers de cache local (LocalCacheFileSystem), après quoi le système de fichiers de cache local rappelle (IncremetCounter) au CacheContext. Ensuite, cette chaîne de rappel continuera jusqu'au HiveFileContext, puis jusqu'à RuntimeStats.
Dans Presto, RuntimeStats est utilisé pour collecter des informations sur les métriques lors de l'exécution de requêtes afin que nous puissions effectuer des opérations d'agrégation. Après cela, nous pouvons voir les informations sur le système de fichiers de cache local dans l'interface utilisateur de Presto ou le fichier JSON. Nous pouvons faire en sorte qu'Alluxio et Presto travaillent en étroite collaboration avec le processus ci-dessus. Du côté de Presto, nous avons de meilleures statistiques ; du côté d'Alluxio, on a une vision plus claire des métadonnées.
Étant donné que le processus de rappel décrit ci-dessus augmente considérablement le cycle de vie de CacheContext, nous avons rencontré des problèmes avec l'augmentation de la latence du GC, que nous travaillons à résoudre.
Nous mettrons en œuvre le cache sémantique (SC) basé sur les métadonnées au niveau du fichier que nous proposons. Par exemple, nous pouvons enregistrer les structures de données dans des fichiers Parquet ou ORC, tels que le pied de page, l'index, etc.
Pour obtenir une désérialisation plus efficace, nous utiliserons flatbuf au lieu de protobuf. Bien que protobuf soit utilisé dans l'usine ORC pour stocker les métadonnées, nous avons constaté que les métadonnées de l'ORC apportent plus de 20 à 30 % de l'utilisation totale du processeur dans la collaboration d'Alluxio avec Facebook. Par conséquent, nous prévoyons de remplacer le protobuf existant par un flatbuf pour stocker le cache et les métadonnées, ce qui devrait améliorer considérablement les performances de la désérialisation.
Pour résumer, avec le blog précédent, cette série de blogs en deux parties explique comment nous avons créé une nouvelle couche de mise en cache des données chaudes nécessaires à notre flotte Presto sur la base d'une récente collaboration open source entre les communautés Presto et Alluxio chez Uber. Cette approche architecturalement simple et propre peut réduire considérablement la latence HDFS avec un SSD géré et une planification d'affinité douce basée sur le hachage cohérente. Rejoignez plus de 9 000 membres sur notre chaîne communautaire Slack pour en savoir plus.
Chen Liang est ingénieur logiciel senior au sein de l'équipe d'analyse interactive d'Uber, se concentrant sur Presto. Avant de rejoindre Uber, Chen était ingénieur logiciel au sein de la plateforme Big Data de LinkedIn. Chen est également committer et membre PMC d'Apache Hadoop. Chen est titulaire de deux maîtrises de l'Université Duke et de l'Université Brown
Le Dr Beinan Wang est un ingénieur logiciel d'Alluxio et est le committer de PrestoDB. Avant Alluxio, il était le responsable technique de l'équipe Presto sur Twitter, et il a construit des systèmes SQL distribués à grande échelle pour la plate-forme de données de Twitter. Il a douze ans d'expérience dans l'optimisation des performances, la mise en cache distribuée et le traitement des données en volume. Il a obtenu son doctorat. en génie informatique de l'Université de Syracuse sur la vérification de modèles symboliques et la vérification d'exécution de systèmes distribués.
Également publié ici.