Maison > développement back-end > Tutoriel Python > Comprendre et appliquer les stratégies de réglage d'Apache Spark

Comprendre et appliquer les stratégies de réglage d'Apache Spark

DDD
Libérer: 2024-11-12 17:55:02
original
727 Les gens l'ont consulté

Motivateurs pour lire cet article.

  • Propre expérience vécue dans des moments de chaos et des moments d'analyse calme.
  • Ce que je cherchais pour approfondir.
  • Ce que j'ai appris sur le fonctionnement de Spark pour l'optimisation.
  • Quel est le « plus » des Databricks pour l'optimisation.
  • Bonnes pratiques qui peuvent éviter le besoin de réglage et de refactorisation.

Introduction

J'ai toujours eu un excellent contact avec les bases de données relationnelles et plus tard avec les systèmes distribués comme Spark. Dans un premier temps, j'ai approfondi le SGBD, à la fois pour mettre en place des requêtes complexes, l'administration et surtout comment mettre en place un script performatif pour le SGBD. Lorsque j'ai commencé à travailler davantage avec Spark et plus tard avec Databricks, au départ je n'avais pas de problèmes de performances pour les scénarios que je devais créer, mais à mesure que le domaine du bigdata devenait vraiment du bigdata, j'ai commencé à avoir des problèmes de performances dans les routines qui augmentaient de 30 % chaque semaine et cela m'a fait chercher comment Spark fonctionne « sous le capot », principalement parce que je savais déjà comment fonctionnait un SGBD et cela m'a aidé à comprendre certains concepts que j'apporterai ici.

Brève explication des composants Apache Spark

Soyons brefs car je souhaite que cet article se concentre sur les scénarios, les techniques et les meilleures pratiques d'analyse des performances.

SparkCore :

Ce composant est la base de Spark, il est responsable de la gestion de la mémoire, des tâches, de la reprise après incident, de la gestion des E/S, autrement dit, il manipule le RDD. C'est donc un gars qui possède une grande partie du cluster.

Exécuteurs testamentaires :

Ce composant est le véritable travailleur de l'écosystème spark (cluster), c'est celui qui reçoit les ordres d'écriture ou de lecture (tâches), qui peuvent être sur disque, en mémoire ou les deux (j'expliquerai plus tard pourquoi cela entre en jeu jouer). scénarios de performance).

ouvriers:

Les travailleurs sont littéralement ce qu'ils sont pour ceux qui sont déjà familiers avec l'informatique distribuée, ce sont les nœuds du cluster, c'est donc ce qui « héberge » les exécuteurs que j'ai mentionnés ci-dessus, chaque travailleur peut contenir un ou plusieurs exécuteurs. Il est chargé de gérer les ressources allouées aux exécuteurs testamentaires, comme si l'exécuteur testamentaire était un assistant et l'ouvrier un magasinier. Et s'il était l'entrepôt dont il relève ?

Gestionnaire de cluster :

C'est le manager, il gère les ressources (Mémoire et CPU) pour les travailleurs, c'est lui qui décide du nombre d'exécuteurs pour chaque application et de la quantité de ressources qui sera allouée, il gère les tâches envoyées par son ' boss' que j'expliquerai plus loin, et comme il s'agit d'un poste de responsabilité plus élevé, il surveille également l'état du cluster pour se remettre des pannes, en redistribuant les tâches si nécessaire. (REMARQUE : il existe plusieurs types de gestionnaires de cluster : Yarn, mesos, kubernetes et le plus simple qui est autonome).

Contexte Spark :

Eh bien, c'est le patron ou la passerelle, je dis passerelle car toute application Spark va passer par elle, c'est ce qui permet à l'application d'interagir avec le cluster, c'est à dire les Workers et les exécuteurs, c'est lui qui permet et gère tâches entre les travailleurs et gère ainsi l'ensemble de l'application en termes de configuration, de nombre d'exécuteurs et de ressources telles que la mémoire. Avez-vous besoin de savoir comment les tâches sont exécutées ? parlez à ce patron ici.

Donc, de manière illustrative :

Entendendo e aplicando estratégias de tunning Apache Spark

Parlons maintenant des performances, du réglage, de la vitesse, de la vitesse et de tout ce que vous entendez depuis différentes positions.

Lorsque je travaillais du côté de la banque relationnelle et qu'il y avait des problèmes de performances, principalement au niveau des procédures ou des fonctions ou d'une requête dans une application, j'ai analysé les aspects suivants :

  1. Quand ce script est-il exécuté et à quoi ressemble le serveur en ce moment ?
  2. Quelqu'un est-il en compétition pour les ressources ou les verrous de table ?
  3. Tout se passe bien, personne ne bloque (bloquant) les ressources du serveur sont bonnes, super...
  4. Maintenant, laissez-moi voir le script, sa logique est-elle performative ? Autrement dit, celui qui a pensé à lire/écrire ensemble ou à y réfléchir ligne par ligne (dépendance à la programmation), consulte trop de colonnes dont il n'avait pas besoin, des requêtes monstrueuses avec sous-requête, CTE, etc. J'ai modifié tous ces points (refactoring) et testé à la fois la rapidité de réponse et l'utilisation des ressources du serveur. Pourquoi est-ce que j'explique tout cela, alors que nous allons parler d'Apache Spark ? Donc... cela s'applique également à Spark et d'une manière que je dirais encore plus complexe, mais nous y arriverons.
  5. Je pense qu'enfin, si le scénario était bon, j'analyserais le « chemin des pierres », c'est-à-dire le plan d'exécution estimé et le plan d'exécution réel. A partir de là, j'ai pu comprendre ce que faisait le SGBD avec ses statistiques (histogramme) et quel chemin il supposait suivre avec ses informations et quelle était la réalité, quel chemin était suivi. Et puis vous pourriez identifier des points tels que : un filtre supplémentaire dans la requête, un JOIN plus performant et même la création d'un index ou de tables temporaires.

Eh bien, je pense que c'est tout, maintenant qu'est-ce que ces points ont en commun avec Apache Spark ?

  • Script non conçu pour la manipulation d'ensembles distribués (j'ai dit que Spark a un 'plus' de difficulté mdr).
  • Heure d'exécution d'une certaine routine, si un simple Job Spark s'exécute dans le même cluster qu'un autre Job performant (ou même pas) qui consomme toutes les ressources. (Regardez une sorte de célèbre verrou de SGBD ici).
  • Et enfin, oui, Apache Spark a un plan d'exécution, pour être plus précis, il comporte les étapes suivantes :
  1. Plan logique.
  2. Plan physique.
  3. Stratégie d'exécution.
  4. Affiche parfois le coût estimé.

Pour résumer ce qu'est chacun, malgré le nom, vous pouvez déjà vous faire une idée :

Plan logique :
Représente la requête d'origine sous la forme d'une série d'opérations logiques. Il s’agit de la forme abstraite de la requête, sans tenir compte de la manière dont elle sera réellement exécutée. Comprend des informations sur les opérations qui seront effectuées, telles que le filtrage, la sélection, la jointure, l'agrégation et les mauvaises « petites choses » aussi mdr.

Plan physique :
Détaille comment Spark exécutera réellement la requête. Cela inclut l'ordre des opérations et les algorithmes qui seront utilisés (comme les algorithmes du SGBD). Il peut inclure des détails sur la façon dont les données seront partitionnées et distribuées entre les exécuteurs testamentaires.

Stratégies d'exécution :
Le plan physique peut afficher différentes stratégies d'exécution que Spark peut utiliser, telles que « Broadcast Join » ou « Shuffle Hash Join », en fonction de l'opération et de la taille des données. Je vais également vous expliquer les principaux algorithmes du plan d'exécution, calmez-vous...

Coût estimé :
Bien qu'ils ne soient pas toujours affichés, certains plans peuvent inclure des estimations de coûts pour différentes parties du plan, vous aidant ainsi à comprendre quelle partie du traitement peut être la plus coûteuse.

Façons d'afficher le plan d'exécution d'Apache Spark

Nous avons le formulaire 'racine' qui serait textuel, en utilisant la commande expliquer() et il aura une sortie similaire à celle ci-dessous montrant un simple filtre et un dataframe :

== Plan Physique ==
*(2) Filtre (Valeur > 1)
- *(2) Projet [Nom#0, Valeur#1]
- *(1) Analyser le RDD existant[Nom#0, Valeur#1]

Et objectivement, on peut l'analyser via l'interface, via l'UI Spark, dans Databricks on peut y accéder, que ce soit dans les exécutions de cellules, dans le job ou dans le cluster. Dans Apache Spark c'est directement l'IP sur le port par défaut 4040.

Spark UI est divisé en plusieurs sections utiles :

  • Tâches : affiche une liste de toutes les tâches exécutées dans l'application. Chaque job correspond à une action dans votre code.

  • Étapes : Affiche les étapes qui composent chaque tâche. Les étapes sont des subdivisions de travail qui peuvent être effectuées en parallèle.

  • Tâches : détaille les tâches individuelles au sein de chaque étape, y compris des informations sur le temps et l'état d'exécution des tâches.

  • Stockage : fournit des informations sur l'utilisation de la mémoire et du stockage des RDD (Resilient Distributed Datasets).

  • Environnement : affiche les propriétés de l'environnement d'exécution, y compris les configurations Spark et les variables système.

  • Exécuteurs : affiche des informations sur les exécuteurs créés pour l'application, y compris l'utilisation de la mémoire, l'utilisation du disque et les statistiques de performances.

Ici, j'étais hiérarchique, d'accord ? C'est l'ordre dans lequel les choses fonctionnent.

Je veux que les images soient mises à l'écran !!

Entendendo e aplicando estratégias de tunning Apache Spark

Entendendo e aplicando estratégias de tunning Apache Spark

Entendendo e aplicando estratégias de tunning Apache Spark

Algorithmes Spark et comment savoir qui sont les contrevenants au réglage :

Tout d'abord, j'expliquerai les principaux algorithmes qui sont démontrés à la fois dans l'interface Spark UI et dans le plan d'exécution, qu'il s'agisse du plan logique ou physique :

REMARQUE : N'oubliez pas que les ensembles de données sont ici les mêmes qu'une table Spark ;)

1. Commençons par le Scan le plus connu :

  • FileScan : lit les données des fichiers d'entrée. Il peut être optimisé pour différents formats de fichiers tels que parquet, ORC, CSV, JSON et ainsi de suite.

2. Rejoignez (Celui-ci donne du B.O) :

  • Broadcast Hash Join : utilisé lorsqu'un des ensembles de données est suffisamment petit pour être transmis à tous les nœuds du cluster, évitant ainsi Shuffle (j'expliquerai plus à ce sujet, mais en bref, c'est une opération de brassage de données pour jointure finale).

  • Shuffle Hash Join : les deux ensembles de données (les tables si vous préférez) sont mélangés afin que les clés correspondantes soient dans la même partition. Il est utilisé lorsque les ensembles de données sont volumineux et ne peuvent pas être transmis à d'autres nœuds.

  • Trier la jointure par fusion : nécessite que les deux ensembles de données soient triés avant la jointure. Il est efficace pour les grands ensembles de données déjà partitionnés et ordonnés, c'est-à-dire que la jointure est effectuée par colonnes partitionnées et également ordonnées (par exemple df.write.partitionBy("coluna1").sortBy("coluna2").parquet(" chemin /vers/enregistrer/partitionné")

3. Agrégation (somme, décompte, regrouper par etc...) :

  • HashAggregate : utilise une table de hachage pour agréger les données. Il est efficace pour les grands ensembles de données qui tiennent en mémoire.

  • TrierAggregate. Agrége les données après les avoir triées. Il est utilisé lorsque les données ne tiennent pas en mémoire.

4. Shuffle (Attention à ce type) :

  • Shuffle : redistribue les données entre les partitions pour les opérations qui nécessitent une réorganisation, telles que les jointures et les agrégations. C'est une opération coûteuse en termes d'E/S et de réseau.

5. Échange :

  • Modifie la répartition des données entre les partitions. Il peut être utilisé pour équilibrer la charge de travail entre les nœuds du cluster. (une stratégie pour équilibrer et échapper au shuffle)

Entendendo e aplicando estratégias de tunning Apache Spark

6. Projet :

  • Sélectionne un sous-ensemble de colonnes à partir d'un DataFrame ou d'un RDD.

7. Filtre :

  • Applique des conditions pour filtrer les lignes de données.

8. Trier :

  • Commandes les données en fonction d'une ou plusieurs colonnes.

Tous ces algorithmes ci-dessus peuvent être observés comme je l'ai dit précédemment via la commande expliquer().

Scénarios réels de problèmes de lecture aléatoire :

1. Rejoindre et opérations GroupBy
Des opérations telles que join() et groupByKey() déclenchent souvent un shuffle, qui redistribue les données entre les partitions. Cela peut entraîner :
Utilisation élevée des E/S disque : Shuffle génère de nombreux fichiers intermédiaires, qui peuvent saturer le disque local des exécuteurs.
Charge réseau élevée : La quantité de données transférées entre les exécuteurs peut être importante, en fonction du nombre de connexions requises (nombre de mappeurs multiplié par le nombre de réducteurs)

  • Identification : Dans Spark UI, dans l’onglet Stage, vérifiez les valeurs Shuffle Read Size/Records et Shuffle Spill (Disk). Un volume élevé dans ces métriques indique un problème potentiel.
  1. Déséquilibre de partition (déséquilibre des données) Lorsque les données sont inégalement réparties entre les partitions, certaines tâches peuvent prendre beaucoup plus de temps que d'autres, ce qui compromet les performances globales. L'identification est la même, allez sur Spark UI, allez sur le travail faisant référence à la section qui prend du temps (voici un point de bonne pratique que je mentionnerai ci-dessous) et vérifiez l'étape bloquée (elle est en cours d'exécution, mais ne fonctionne pas progression) et voir les métriques Shuffle, en général, un volume élevé en mémoire et commencer à avoir du volume sur le disque lorsque vous actualisez cela indique que ce déséquilibre a atteint la mémoire et a commencé à écrire sur le disque et évidemment le disque est plus lent, alors vous vous asseyez et pleure si tu laisses ce scénario.

Atténuation

  • Pour atténuer les problèmes liés à la lecture aléatoire : Réduisez les opérations qui provoquent un brassage : dans la mesure du possible, minimisez le Utilisez groupByKey() et préférez réduireByKey(). Ajustez le nombre de Partitions : utilisez spark.sql.shuffle.partitions pour ajuster le nombre de Partitions pendant les opérations de lecture aléatoire. Utilisez des techniques telles que Broadcast Joins : pour joindre de grands ensembles de Données avec des ensembles plus petits, évitant ainsi une lecture inutile.

Mélanger les métriques dans Spark UI :

Entendendo e aplicando estratégias de tunning Apache Spark

Comment fonctionne le mélange et pourquoi il est coûteux :

Entendendo e aplicando estratégias de tunning Apache Spark

Enfin et peut-être le plus important - Bonnes pratiques :

  1. La grande majorité travaille avec des notebooks en raison de la grande popularité de Databricks, Jupyter notebook et Google Colab. Par conséquent, divisez chaque requête ou transformation en cellules distinctes, cela permet d'identifier plus facilement quelle partie pose problème de performances. En mettant tout ensemble, il y a plusieurs travaux et il est difficile de savoir à quelle étape en est.

  2. Utilisez Fusion au lieu d'Écraser, je sais que c'est plus de travail, mais c'est plus logique et plus performant, car La fusion utilisera moins d'E/S qu'un écrasement de « vidage » de la table entière à nouveau dans le lac de données.

  3. Utilisez cache() ou persist() pour stocker les données intermédiaires en mémoire, surtout si elles seront réutilisées lors de plusieurs opérations. Cela peut réduire le temps de recalcul et améliorer les performances.

  4. Au cas où vous ne le sauriez pas, Spark fonctionne sur une JVM donc c'est nativement Java, lorsque vous créez le fameux UDF - User Definition Function avec Python vous laissez une sorte de "boîte noire" pour Spark, empêchant optimisations automatiques. Dans la mesure du possible, utilisez les fonctions Spark SQL intégrées, optimisées pour les performances.

Eh bien, je pense avoir écrit tout ce que j'avais en tête, j'aime écrire des articles car cela m'aide à me souvenir de certains scénarios. J'ai l'intention d'enregistrer une vidéo montrant tout cela, en pratique avec quelques données publiques, je l'aurai probablement sur Kaggle alors suivez-moi sur LinkedIn pour suivre tout ce qui touche au monde de la donnée, de l'intelligence artificielle et du développement logiciel

--> https://www.linkedin.com/in/airton-lira-junior-6b81a661

Suivez-moi sur LinkedIn, donnez-moi un coup de pouce, j'aime les retours et je suis également totalement ouvert à l'amélioration du partage des connaissances.

Si vous avez lu jusqu'ici, félicitations !!! J'espère que cela résoudra tous les problèmes de performances. Dans le prochain article, j'aborderai les avantages de Databricks, alors suivez-moi sur LinkedIn pour le découvrir. Merci !!

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal