Heim  >  Artikel  >  Backend-Entwicklung  >  Codierungsaufgaben abschätzen: Was könnte schiefgehen?

Codierungsaufgaben abschätzen: Was könnte schiefgehen?

WBOY
WBOYOriginal
2024-08-11 12:40:021134Durchsuche

Estimating Coding Tasks: What Could Go Wrong?

Hier erfahren Sie, wie sich die Aufgabe „Hinzufügen eines Hashs zu einem vorhandenen DataFrame“ von ein paar Tagen zu fast einem ganzen Sprint entwickelt hat.

Im zweiten Quartal 2022 begann ich mit der Arbeit an einer Datenpipeline, die Marktdaten von einem REST-Dienst abruft und in einer BigQuery-Tabelle speichert. Dies ist eine allgemeine Erklärung der Pipeline. Der interessante Teil besteht darin, wie die Daten abgefragt, in DataFrame konvertiert und dann mit GCSToBigQueryOperator von AirFlow in BigQuery-Tabellen hochgeladen werden.

Anfangs schien es einfach zu schreiben, aber das „idempotente“ Prinzip von Airflow machte es zu einer kleinen Herausforderung. Was von diesem REST-Dienst abgerufen werden soll, wurde von einer anderen Tabelle entschieden, und selbst wenn JOB idempotent ist, könnte sich die als Referenz verwendete Tabelle zwischen zwei Läufen ändern. Nachdem wir zusätzliche Zeit aufgewendet hatten, war das Gespräch mit den Data Engineers-Pipelines bis zum Ende des dritten Quartals 2022 fertig.

Schneller Vorlauf zum ersten Quartal 2024. Zu diesem Zeitpunkt hatten wir mehr Benutzer, die auf die Daten zugegriffen haben, und wir stellten fest, dass unser Abfragemuster Partitionen nicht richtig nutzte. Oder besser gesagt, wir wollten auf die Daten basierend auf einer String-Spalte zugreifen, aber eine Partitionierung nach einer String-Spalte ist in BigQuery nicht möglich. Dies führte dazu, dass große Datenmengen gescannt wurden und häufig das Tageskontingent erreicht wurde.

Dies veranlasste uns, darüber nachzudenken, wie Daten basierend auf Zeichenfolgenspalten partitioniert werden können. Unser Dateningenieur schlug vor, diese Zeichenfolgenspalte mithilfe von FarmHash mit einer zusätzlichen Modulo-Operation in eine Ganzzahl umzuwandeln. Im Proof of Concept wurde dadurch das Scannen um fast 90 % reduziert und die Abfrageleistung um das 3- bis 5-fache erhöht. Wir haben uns entschieden, dies als endgültige Lösung zu wählen. Alles was wir brauchten war:

  1. Erstellen Sie eine Tabelle mit Farmhash-Fingerabdruck
  2. Pipeline ändern, um den Fingerabdruck zu berechnen
  3. Laden Sie die Daten hoch.

Um FarmHash-Fingerabdrücke in Python zu berechnen, gibt es ein Pyfarmhash-Modul. Ich habe das Modul installiert und den Code unten verwendet, um den Hash zu berechnen, und lokal hat alles wie gewünscht funktioniert.

def get_hash(val: str) -> int:
    return additonal_logic(pyfarmhash.fingerprint64(...))

df[‘hash’] = df[‘Col’].apply(get_hash)

Nachdem alle Tests bestanden waren, war es nun an der Zeit, den Code an Airflow zu übertragen und auszuführen. Ich hatte zu diesem Zeitpunkt nicht damit gerechnet, dass etwas schief gehen würde. Tatsächlich war ich froh, dass alles wie geplant und innerhalb der geschätzten Zeit geklappt hat.

Mit einem glücklichen Geist und voller Zuversicht habe ich meine Änderungen vorangetrieben, mit der Arbeit begonnen und dann 10 bis 15 Minuten gewartet, bis sie abgeschlossen war. In der Zwischenzeit habe ich mich einer anderen Aufgabe zugewandt. Bald erhielt ich eine unerwartete Fehler-E-Mail von Airflow. Ich habe mir die Protokolle angesehen und war überrascht, dass bei der Installation des Pyfarmhash-Moduls ein Fehler aufgetreten ist!

Um Ihnen das Verständnis des Problems zu erleichtern, muss ich die Struktur des Jobs erklären. Der Job besteht aus den folgenden Schritten:

  1. Laden Sie die Daten im Parkettformat herunter
  2. In den GCS-Bucket hochladen
  3. Vorhandene Daten löschen; wenn überhaupt. (doppelte Daten vermeiden)
  4. Laden Sie die Daten in BQ-Tabellen hoch.

In diesem Prozess ist Aufgabe 1, die die Daten herunterlädt, ein separates Python-Modul. Um es auszuführen, habe ich den PythonVirtualenvOperator von Airflow verwendet. Mit diesem Operator können Sie Pakete als Anforderungen angeben und diese dann in einer neu erstellten virtuellen Umgebung installieren. Sobald das Paket installiert ist, werden auch alle seine Abhängigkeiten installiert und Sie können loslegen.

Ich habe pyfarmhash als Abhängigkeit zum Modul hinzugefügt, das die Daten herunterlädt, und alles andere blieb unverändert. Und es ist gescheitert! Warum?

pyfarmhash ist eine in C/C++ implementierte Hashing-Bibliothek. Bei der Installation muss GCC das Paket kompilieren, und dieses war auf dem Airflow-Host nicht vorhanden. Es machte Sinn, GCC nicht auf dem Airflow-Host zu haben, aber leider war dies ein Blocker für mich.

Ich habe nach einer reinen Python-Implementierung des Pyfarmhash-Pakets gesucht, aber es gab keine. Dann suchte ich nach Radpaketen, aber auch hier gab es keine. Ich habe darüber nachgedacht, Radpakete zu bauen und voranzutreiben, aber das hätte zu einer langfristigen Verantwortung für die interne Bereitstellung von Radpaketen geführt. Ich wollte zusätzliche, Workaround-ähnliche Schritte vermeiden. Ich habe alle Optionen untersucht und sie mit dem Team besprochen, das Airflow verwaltet. Sie schlugen vor, ein Docker-Image zu erstellen und es in KubernetesPodOperator auszuführen. Dies war eine gute Option, da ich die Umgebung steuern und alles einbeziehen konnte, was erforderlich war, ohne auf eine externe Umgebung angewiesen zu sein. Darüber hinaus gab es für diese Lösung keine Problemumgehungen. Der einzige kurzfristige Nachteil war, dass die Umsetzung mehr Zeit in Anspruch nahm.

Bevor ich mit einer Docker-basierten Lösung begann, hatte ich bereits etwa 16–20 Stunden mit dieser Aufgabe verbracht. Für die Docker-basierte Lösung musste ich außerdem Folgendes tun:

  1. Ändern Sie das Python-Paket so, dass es Einstiegspunkte zum Starten des Downloads und zum Löschen der Logik hat.
  2. Erstellen Sie ein Docker-Paket und testen Sie es (dies war mein zweites Docker-Image).

Da ich PythonVirtualEnvOperator nicht mehr in Airflow verwenden wollte, habe ich beschlossen, es vollständig zu entfernen und so den Workflow zu verbessern. Ich musste das Python-Paket ändern, um Einstiegspunkte zu haben, um den Download und die Löschlogik zu starten

Es dauerte weitere 30 bis 36 Stunden, bis ich eine endgültige Lösung mit dem Docker-Image fertig hatte, was 6 bis 7 Arbeitstage entspricht. Zusammen mit den ersten zwei Tagen wurde es zu einer sprintlangen Aufgabe.

Wenn ich darauf zurückblicke, wundere ich mich, dass ich die funktionierende Lösung wegwerfen, die Modulstruktur ändern, ein Docker-Image erstellen, mehr als 10 AirFlow-Jobs ändern musste, um das Docker-Image für Aufgaben zu verwenden, mich mit dieser Realität auseinandersetzen und die anfängliche Frustration überwinden musste. Und das nur, weil „ein einzelnes Python-Modul „gcc“ zum Kompilieren benötigte!“

Das obige ist der detaillierte Inhalt vonCodierungsaufgaben abschätzen: Was könnte schiefgehen?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn