Zurück zu den Neuigkeiten für Entwickler

Erfahrungswerte: Einsatz von Presto im Meta-Maßstab

11. April 2023VonNeerad Somanchi und Philip Bell

Presto ist eine kostenlose Open-Source-Abfrage-Engine für SQL. Wir benutzen Presto bei Meta seit zehn Jahren und haben dabei viel gelernt. Egal ob Tools, Prozesse oder Services: Die Ausführung im großen Maßstab erfordert Problemlösungen, um erwartete Herausforderungen meistern zu können. Hier sind vier Dinge, die wir beim Hochskalieren von Presto auf den Meta-Maßstab gelernt haben, und einige Hinweise, falls du Interesse daran hast, deine eigenen Abfragen im großen Maßstab auszuführen.

Schnelle Skalierung von Presto, um den wachsenden Anforderungen gerecht zu werden: Vor welchen Herausforderungen standen wir?

Bereitstellen neuer Presto-Versionen

Abbildung 1: Prozess-Workflow zum Veröffentlichen neuer Presto-Versionen (Diagramm von Philip S. Bell)

Meta führt weltweit in verschiedenen Rechenzentren eine große Anzahl an Presto-Clustern aus. Ungefähr ein- bis zweimal pro Monat wird eine neue Version von Presto entwickelt und bereitgestellt. Eine der anfänglichen Herausforderungen, als Presto immer mehr bei Meta eingesetzt wurde, war die Bereitstellung der Abfrage-Engine für eine große Anzahl an Clustern bei gleichzeitiger Gewährleistung einer konsistenten Verfügbarkeit und Zuverlässigkeit. Dies ist immer noch bei interaktiven Anwendungsfällen von Presto der Fall, z. B. wenn Nutzer*innen Abfragen starten und aktiv auf ein Ergebnis warten. Abfragefehler sind weniger problematisch für automatisierte „Batch“-Anwendungsfälle, in denen automatische Neuversuche sicherstellen, dass die Abfrage letztendlich erfolgreich ist.

Die Lösung hierfür war simpel. Alle Presto-Cluster befinden sich hinter einem Load Balancer – dem Gateway – welcher (in Verbindung mit anderen Systemen bei Meta) dafür verantwortlich ist, Presto-Abfragen an das entsprechende Cluster weiterzuleiten. Wenn ein Presto-Cluster aktualisiert werden muss, wird es zunächst vom Gateway als „geleert“ markiert, das heißt, das Gateway stoppt die Weiterleitung aller neuen Abfragen an dieses Cluster. Die Automatisierung wartet danach einen vorgegebenen Zeitraum ab, damit die auf dem Cluster ausgeführten Abfragen abgeschlossen werden können. Das Cluster wird dann aktualisiert. Wenn es wieder online ist, wird es für das Gateway sichtbar gemacht. Somit kann es wieder neue Abfragen an das Cluster weiterleiten.

Der andere Aspekt bei der Bereitstellung neuer Presto-Versionen ist die Verfügbarkeit. Wir müssen sicherstellen, dass Nutzer*innen Presto weiterhin verwenden können, während Cluster aktualisiert werden. Auch hier gewährleistet die Automatisierung, dass jedes Rechenzentrum in jeder physischen Region stets über die erforderliche Anzahl an Presto-Clustern verfügt. Natürlich dürfen weder zu viele (Verfügbarkeitsproblem) noch zu wenige Cluster (Bereitstellung dauert zu lange) gleichzeitig abgeschaltet werden.

Automatisierung des Hochfahrens und Außerbetriebnehmens von Presto-Clustern

Abbildung 2: Automatisierter Workflow für das Hinzufügen von Hardware zu Clustern (Diagramm von Philip S. Bell)

Die geographische Verteilung der Data Warehouses von Meta ist stets im Wandel. Dies bedeutet, dass neue Presto-Cluster hochgefahren werden müssen und bestehende Cluster regelmäßig außer Betrieb genommen werden. Zuvor, als es nur eine kleine Anzahl an Presto-Clustern gab, war dies ein manueller Prozess. Als Meta mit der Hochskalierung begann, wurde es schnell kompliziert, alle Änderungen manuell nachzuverfolgen. Wir haben automatisierte Prozesse für das Hochfahren und Außerbetriebnehmen von Clustern implementiert, um dieses Problem zu lösen.

Wir mussten zunächst unsere Cluster-Konfigurationen standardisieren. Das bedeutet, dass wir Basiskonfigurationen für die unterschiedlichen Anwendungsfälle von Presto bei Meta entwickeln mussten. Jedes Cluster hatte dann über die Basiskonfiguration hinaus eine minimale Anzahl an zusätzlichen oder überschriebenen Spezifikationen. Als dies abgeschlossen war, konnte jedes neue Cluster hochgefahren werden, indem Konfigurationen automatisch von der Basisvorlage generiert wurden. Das Hochfahren von Clustern erforderte außerdem eine Integration mit Automatisierungs-Hooks, um mit den unterschiedlichen unternehmensweiten Infrastrukturdiensten wie Tupperware und Data-Warehouse-spezifischen Diensten integriert zu werden. Sobald ein Cluster online geht, werden einige Testabfragen an das Cluster gesendet und die Automatisierung verifiziert, dass die Abfragen erfolgreich vom Cluster ausgeführt wurden. Das Cluster wird dann beim Gateway registriert und beginnt mit dem Verarbeiten von Abfragen.

Die Außerbetriebnahme eines Clusters folgt so ziemlich dem umgekehrten Prozess. Das Cluster wird vom Gateway abgemeldet und alle laufenden Abfragen werden abgeschlossen. Die Presto-Prozesse werden heruntergefahren und die Cluster-Konfigurationen werden gelöscht.

Diese Automatisierung ist im Data-Warehouse-Workflow für das Hochfahren und Außerbetriebnehmen integriert. Letztendlich heißt das, dass der gesamte Prozess, vom Empfang neuer Hardware im Rechenzentrum über aktive Presto-Cluster, die Abfragen verarbeiten, bis hin zur Abschaltung bei der Außerbetriebnahme der Hardware, vollständig automatisiert ist. Die Implementierung hat wertvolle Arbeitszeit gespart, Leerlaufzeiten der Hardware reduziert und menschliche Fehler minimiert.

Automatisiertes Debuggen und Beheben

Abbildung 3: Erkennung fehlerhafter Hosts (Diagramm von Philip S. Bell)

Angesichts der großflächigen Bereitstellung von Presto bei Meta ist es unerlässlich, dass wir über Tools und Automatisierung verfügen, die das Leben des Bereitschaftsdienstes (die Kontaktstelle für Presto) erleichtern.

Wir haben im Laufe der Jahre mehrere „Analysatoren“ entwickelt, die dem Bereitschaftsdienst beim effizienten Debuggen und Ermitteln der Grundursache für auftretende Probleme unterstützen. Überwachungssysteme senden Warnungen, wenn Fehler bei kund*innenseitigen SLAs vorliegen. Die Analysatoren werden dann ausgelöst. Sie sammeln Informationen von vielen verschiedenen Überwachungssystemen (Operational Data Store oder ODS), von auf Scuba veröffentlichten Ereignissen und sogar von Protokollen auf Hostebene. Die selbstdefinierte Logik des Analysators verknüpft dann all diese Informationen, um auf die wahrscheinliche Grundursache zu schließen. Dies ist für den Bereitschaftsdienst äußerst nützlich, da ihm die Analyse zur Grundursache bereitgestellt wird, wodurch er direkt mit potenziellen Behebungsmaßnahmen beginnen kann. In einigen Fällen haben wir sowohl das Debugging als auch die Fehlerbehebung vollständig automatisiert, sodass der Bereitschaftsdienst nicht einmal eingreifen muss. Im Folgenden werden einige Beispiele beschrieben:

Erkennung fehlerhafter Hosts

Beim Ausführen von Presto im großen Maßstab auf einer großen Anzahl an Rechnern haben wir festgestellt, dass einige fehlerhafte Hosts unverhältnismäßig viele Abfragefehler verursachen können. Bei unseren Untersuchungen haben wir einige Grundursachen identifiziert, die dazu führten, dass die Hosts fehlerbehaftet wurden:

  • Probleme auf Hardware-Ebene, die aufgrund fehlender Abdeckung noch nicht von flottenübergreifenden Überwachungssystemen erfasst wurden
  • Verborgene JVM-Bugs, die manchmal zu einem wiederholten Auftreten von Abfragefehlern führen

Wir überwachen mittlerweile Abfragefehler in Presto-Clustern, um dieses Problem zu bekämpfen. Insbesondere ordnen wir, wenn möglich, jeden Abfragefehler dem Host zu, der ihn verursacht hat. Wir richten außerdem Warnungen ein, die ausgelöst werden, wenn eine ungewöhnlich hohe Anzahl an Abfragefehlern bestimmten Hosts zugeordnet wird. Die Automatisierung springt dann ein, um den Host aus der Presto-Flotte zu entleeren und somit die Fehler einzudämmen.

Debugging von Warteschlangenproblemen

Jedes Presto-Cluster unterstützt das Einreihen von Abrufen in eigene Warteschlangen, sobald es seine maximale gleichzeitige Ausführung von Abfragen basierend auf Anwendungsfall, Hardwarekonfiguration und Abfragegröße erreicht hat. Bei Meta gibt es einen ausgeklügelten Weiterleitungsmechanismus, damit eine Presto-Abfrage an das richtige Cluster weitergeleitet wird, welches die Abfrage am effizientesten ausführen kann. An der Weiterleitungsentscheidung sind neben Presto weitere Systeme beteiligt, die mehrere Faktoren berücksichtigen:

  • Aktueller Status der Warteschlangen auf Presto-Clustern
  • Verteilung der Hardware in verschiedenen Rechenzentren
  • Der Datenspeicherort der Tabellen, die von der Abfrage verwendet werden

Angesichts dieser Komplexität kann es für den Bereitschaftsdienst sehr schwer sein, die Grundursache von Warteschlangenproblemen in der Produktion zu finden. Dies ist ein weiterer Fall, in dem Analysatoren zum Einsatz kommen, indem sie Informationen aus mehreren Quellen sammeln und Schlussfolgerungen ziehen.

Robustheit des Load Balancers

Abbildung 4: Robustheit des Load Balancers (Diagramm von Philip S. Bell)

Wie oben erwähnt, sitzen unsere Presto-Cluster hinter Load Balancern, die jede einzelne Presto-Query bei Meta weiterleiten. Anfangs, als Presto noch nicht das heutige Ausmaß der internen Nutzung erreicht hatte, war das Gateway sehr simpel. Also jedoch die Nutzung von Presto bei Meta zunahm, stießen wir hin und wieder auf Probleme bei der Skalierbarkeit. Eines der Probleme war, dass das Gateway unter hoher Last ausfiel, was dazu führen konnte, dass Presto für alle Nutzer*innen nicht mehr verfügbar ist. Die Grundursache für einige Stabilitätsprobleme war, dass ein Dienst das Gateway unbeabsichtigt mit Millionen von Abfragen in kurzer Zeit bombardierte, was dazu führte, dass die Gateway-Prozesse abstürzten und keine Abfragen mehr weiterleiten konnten.

Um so ein Szenario zu verhindern, haben wir uns daran gemacht, das Gateway robuster und toleranter gegenüber solchem unbeabsichtigten DDOS-artigen Verkehr zu machen. Wir haben eine Drosselungsfunktion implementiert, die unter hoher Last Abfragen ablehnt. Die Drosselung kann basierend auf der Abfrageanzahl pro Sekunde über verschiedene Dimensionen wie pro Nutzer*in, pro Quelle, pro IP und auch auf globaler Ebene für alle Abfragen aktiviert werden. Eine weitere von uns implementierte Verbesserung war die automatische Skalierung. Mithilfe eines Meta-übergreifenden Dienstes, der die Hoch- und Herunterskalierung von Jobs unterstützt, ist die Anzahl der Gateway-Instanzen nun dynamisch. Dies bedeutet, dass das Gateway unter hoher Last jetzt hochskalieren kann, um den zusätzlichen Verkehr handhaben zu können, ohne die CPU/den Speicher auszulasten. Somit wird das oben beschriebene Absturzszenario verhindert. Dies verhindert zusammen mit der Drosselungsfunktion, dass das Gateway robust ist und unerwünschten, unvorhersehbaren Verkehrsmustern standhalten kann.

Welchen Rat würden wir einem Team geben, das sein eigens Data Lakehouse mit Presto skaliert?

Abbildung 5: Skalierung der Presto-Architektur (Diagramm von Philip S. Bell)

Dies sind einige der wichtigen Aspekte, die bei der Skalierung von Presto zu beachten sind:

  1. Erstellen von leicht verständlichen und klar definierten kundenseitigen SLAs. Das Definieren von SLAs anhand von wichtigen Metriken wie Wartezeit und Abfragefehlerrate in einer Weise, die die Problematiken auf Kund*innenseite nachverfolgt, wird mit zunehmender Skalierung von Presto unerlässlich. Bei einer großen Anzahl an Nutzer*innen kann das Fehlen geeigneter SLAs die Bemühungen zur Behebung von Produktionsproblemen erheblich behindern, da dies zu Verwirrung bei der Ermittlung der Auswirkungen eines Vorfalls führt.
  2. Überwachung und automatisiertes Debugging. Wenn Presto skaliert wird und die Anzahl der Cluster zunimmt, nimmt die Überwachung und das automatisierte Debugging eine entscheidende Rolle ein.
    • Eine gründliche Überwachung kann dabei helfen, Produktionsprobleme zu identifizieren, bevor das Ausmaß der Konsequenzen zu groß wird. Durch frühzeitiges Erkennen von Problemen stellen wir sicher, dass wir die Auswirkungen für Nutzer*innen so gering wie möglich halten.
    • Manuelle Untersuchungen sind angesichts von Produktionsproblemen, die Auswirkungen für Kund*innen haben, nicht skalierbar. Ein automatisiertes Debugging ist zwingend notwendig, damit die Grundursache schnell ermittelt werden kann.
  3. Gutes Load Balancing. Wenn die Presto-Flotte wächst, ist es wichtig, eine gute Load-Balancing-Lösung vor den Presto-Clustern zu haben. Kleine Effizienzprobleme beim Load Balancing können im großen Maßstab aufgrund des Volumens der Arbeitslast eine erhebliche negative Auswirkung haben.
  4. Konfigurationsmanagement. Das Konfigurationsmanagement einer großen Flotte von Presto-Clustern kann mühsam sein, wenn es nicht gut geplant ist. Wo möglich, sollten Konfigurationen im Betrieb wiederladbar sein, sodass Presto-Instanzen nicht auf störende Weise neu gestartet oder aktualisiert werden müssen, was zu Abfragefehlern und Unzufriedenheit bei den Kund*innen führen würde.

Dieser Artikel wurde in Zusammenarbeit mit Neerad Somanchi, einem Production Engineer bei Meta, und Philip Bell, einem Developer Advocate bei Meta, verfasst.

Um mehr über Presto zu erfahren, besuche prestodb.io, schaue dir Philip Bells kurze Erklärung zu Presto auf YouTube an oder folge Presto auf Twitter, Facebook und LinkedIn.

Um mehr über Meta Open Source zu erfahren, besuche unsere Open-Source-Website, abonniere unseren YouTube-Kanal oder folge uns auf Twitter, Facebook und LinkedIn.