ETL w DataFlow

Jak DataFlow AI realizuje ETL

Ta strona podnosi pokrywę platformy DataFlow AI i pokazuje, krok po kroku, jak faktycznie wykonuje ona pracę ETL. Zaczyna się od przystępnego przeglądu, za którym może podążać każdy, a następnie wchodzi głębiej w każdą część dla czytelników, którzy chcą szczegółów technicznych.

Jeśli nie przeczytałeś jeszcze Czym jest ETL?, warto zrobić to najpierw — ta strona zakłada, że wiesz już, czym są Extract, Transform, Load, potok danych, konektor i DAG.


Szeroki obraz — co się dzieje, gdy uruchamiany jest potok danych

Zanim przejdziemy do szczegółów, oto cała historia na jednym oddechu.

Potok danych zaczyna swoje życie jako przepis — pisemny opis każdego kroku. Gdy nadchodzi czas jego uruchomienia (albo dlatego, że zegar osiągnął zaplanowaną godzinę, albo dlatego, że ktoś nacisnął „Uruchom”), platforma odczytuje przepis, starannie sprawdza go pod kątem błędów, ustala właściwą kolejność kroków, a następnie je wykonuje. W trakcie pracy pokazuje na ekranie postęp na żywo. Jeśli krok zawiedzie, próbuje odzyskać się automatycznie. Po zakończeniu odnotowuje, co się wydarzyło — ile wierszy przetworzono, jak długo to trwało oraz czy dane przeszły kontrole jakości.

Oto ta sama historia jako ponumerowana sekwencja:

  1. The recipe is written        →  a YAML file describing every step
  2. The recipe is checked        →  validated against rules; mistakes caught early
  3. A trigger fires              →  the schedule reaches its time, or a person clicks Run
  4. The steps are ordered        →  the DAG engine works out what runs, and in what order
  5. The steps are executed       →  each node does its job; independent steps run together
  6. Progress is shown live       →  rows-in, rows-out, and status stream to the screen
  7. Problems are handled         →  failed steps are retried; recovery is attempted
  8. Quality is checked           →  the data is scored against its rules
  9. The result is recorded       →  row counts, duration, and outcome are saved

Pozostała część tej strony przeprowadza kolejno przez każdy z tych etapów.

Mówiąc prościej

Potok danych to pisemny przepis. Uruchomienie go oznacza: odczytaj przepis, sprawdź go pod kątem błędów, ustal kolejność kroków, wykonaj je, wypatruj kłopotów i zapisz, co się wydarzyło. Wszystko poniżej to po prostu szczegóły dotyczące tego, jak każda z tych rzeczy jest robiona.


Etap 1 — Jak definiowany jest potok danych: przepis w formacie YAML

Każdy potok danych DataFlow AI przechowywany jest jako przepis zapisany w formacie pliku zwanym YAML.

YAML to format zwykłego tekstu zaprojektowany tak, aby był czytelny dla zwykłych ludzi, a nie tylko dla komputerów. Używa prostych wcięć (odstępów), aby pokazać, jak rzeczy są pogrupowane, zamiast nawiasów i symboli większości języków programowania. Możesz otworzyć plik YAML i ogólnie go zrozumieć, nawet jeśli nigdy wcześniej takiego nie widziałeś.

Szczególny styl YAML w DataFlow AI — jego zestaw reguł dotyczących tego, co przepis potoku danych może zawierać — nazywany jest DSL, co oznacza Domain-Specific Language (Język Specyficzny dla Domeny). DSL to po prostu mały, skoncentrowany język zbudowany do jednego zadania; tutaj tym jednym zadaniem jest „opisać potok danych ETL”. Styl jest celowo wzorowany na sposobie, w jaki system Kubernetes (popularne narzędzie do uruchamiania oprogramowania) opisuje swoją konfigurację, dlatego każdy plik potoku danych zaczyna się od wierszy apiVersion i kind.

Kształt pliku potoku danych

Przepis potoku danych ma dwie główne części: metadata (informacje o potoku danych) oraz spec (właściwą specyfikację tego, co robi).

apiVersion: dataflow.polkomtel.com/v1
kind: Pipeline
metadata:
  name: daily-sales-load
  namespace: sales-analytics
  annotations:
    description: "Loads yesterday's sales from Oracle into Snowflake"
    owner: "data-team"
spec:
  schedule: "0 2 * * 1-5"      # run at 02:00, Monday to Friday
  timezone: "Europe/Warsaw"
  enabled: true
  parameters:
    - name: load_date
      type: date
      default: "{{yesterday}}"
  timeout: 3600                 # give up after 3600 seconds (one hour)
  retries: 3                    # if a step fails, try it up to 3 more times
  nodes:
    - id: read-oracle
      type: connector_source
      label: "Read sales from Oracle"
      config:
        connector: oracle-prod
        table: SALES
    - id: drop-tests
      type: filter
      label: "Remove test rows"
      config:
        condition: "status != 'TEST'"
    - id: write-snowflake
      type: connector_sink
      label: "Write to Snowflake"
      config:
        connector: snowflake-dw
        table: FACT_SALES
        writeMode: UPSERT
        upsertKeys: [sale_id]
  edges:
    - from: read-oracle
      to: drop-tests
    - from: drop-tests
      to: write-snowflake

Czytając ten plik od góry do dołu: jest to potok danych o nazwie daily-sales-load; uruchamia się o godzinie 2:00 w dni robocze czasu warszawskiego; ma trzy kroki (nodes) — odczyt z Oracle, usunięcie wierszy testowych, zapis do Snowflake — a edges łączą je w kolejności. Nawet bez przygotowania technicznego kształt przepisu jest możliwy do prześledzenia.

11 typów węzłów

Każdy krok w potoku danych to węzeł, a każdy węzeł ma typ, który decyduje, jakie zadanie wykonuje. DSL DataFlow AI definiuje 11 typów węzłów. Osiem jest przeznaczonych dla potoków wsadowych, a dwa dla strumieniowych; jeden (connector_source) jest współdzielony.

Typ węzłaCo robi
connector_sourceOdczytuje dane z zarejestrowanego konektora — krok Extract.
connector_sinkZapisuje dane do konektora — krok Load. Niesie ze sobą writeMode taki jak INSERT, UPSERT czy OVERWRITE.
expressionPrzekształca kolumny jedna po drugiej — obliczając nowe wartości lub przeformatowując istniejące.
filterOdrzuca wiersze, które nie spełniają warunku; odrzucone wiersze mogą opcjonalnie być wysłane do oddzielnego miejsca docelowego w celu inspekcji.
aggregatorPodsumowuje wiersze w grupy — zadanie „łączna sprzedaż na region”.
joinerZszywa dwa zbiory danych z góry razem na podstawie wspólnego klucza (złączenie INNER, LEFT, RIGHT lub FULL).
routerRozprowadza dane wieloma ścieżkami, z których każda wybierana jest przez własny warunek.
sorterZmienia kolejność wierszy według jednej lub więcej kolumn.
unionSkłada wiersze z kilku węzłów z góry w jeden połączony zbiór, opcjonalnie usuwając duplikaty.
cdc_sourceKonsumuje strumień zmian bazy danych na żywo przechwytywany przez Debezium — używany w potokach strumieniowych.
streaming_sinkZapisuje ciągły strumień do miejsca docelowego takiego jak Kafka.

Parametry i funkcje szablonów

Dobry przepis nie powinien musieć być przepisywany każdego dnia tylko dlatego, że zmieniła się data. DataFlow AI radzi sobie z tym za pomocą parametrów i funkcji szablonów.

Parametr to nazwany slot w przepisie, którego wartość jest wypełniana, gdy potok danych się uruchamia — na przykład load_date. Funkcja szablonu to mały wbudowany pomocnik, zapisany wewnątrz podwójnych nawiasów klamrowych, który automatycznie wypełnia taki slot. Przydatne przykłady obejmują {{today}}, {{yesterday}}, {{now}}, {{date_add(today,-7)}} (data sprzed tygodnia) oraz {{month_start(today)}} (pierwszy dzień bieżącego miesiąca). Istnieje również {{vault:secret/path#key}}, która bezpiecznie pobiera hasło z bezpiecznego magazynu, nigdy nie zapisując go do pliku.

Każdy przepis jest objęty kontrolą wersji

Za każdym razem, gdy potok danych jest zapisywany, DataFlow AI robi automatycznie dwie rzeczy. Po pierwsze, waliduje przepis (omówione w następnym etapie). Po drugie, przechowuje nową wersję w repozytorium Git — Git będąc standardowym narzędziem do prowadzenia pełnej historii zmian w plikach. Każda zapisana wersja otrzymuje numer i unikalny odcisk palca (git_commit_sha), a poprzednia wersja jest zachowywana. Oznacza to, że zawsze możesz spojrzeć wstecz na to, co potok danych kiedyś robił, porównać dwie wersje i cofnąć zmianę, jeśli zajdzie potrzeba.


Etap 2 — Jak sprawdzany jest przepis: walidacja schematu

Zanim potok danych w ogóle zostanie dopuszczony do uruchomienia — w istocie, zanim zostanie nawet zapisany — jego przepis YAML jest walidowany.

Walidacja oznacza, że przepis jest sprawdzany, automatycznie, względem surowego zestawu reguł zwanego JSON Schema. (JSON Schema to formalny opis tego, jak musi wyglądać prawidłowy plik — które pola są wymagane, jakiego typu musi być każde pole i tak dalej). Walidacja wychwytuje błędy takie jak: węzeł, któremu brakuje wymaganego ustawienia, źle zapisany typ węzła, dwa węzły z tym samym identyfikatorem, strzałka wskazująca na węzeł, który nie istnieje, lub węzeł pozostawiony odłączony od reszty diagramu.

Wychwytywanie tych błędów wcześnie — na etapie projektowania i ponownie przed wykonaniem — jest o wiele lepsze niż odkrycie ich w połowie uruchomienia o 3:00 w nocy. Węzeł, który nie przejdzie walidacji, jest oznaczany czerwonym znacznikiem na płótnie. Możesz zapisać potok danych, który nadal ma błędy, ale nie możesz go uruchomić, dopóki każdy błąd nie zostanie rozwiązany.


Etap 3 — Jak potok danych jest wyzwalany

Uruchomienie potoku danych zaczyna się, ponieważ coś go wyzwala. Istnieją trzy rodzaje wyzwalaczy.

  • Harmonogram. Najczęstszy wyzwalacz — zegar osiąga godzinę, na którą potok danych został ustawiony do uruchomienia.
  • Uruchomienie ręczne. Ktoś otwiera potok danych i naciska „Uruchom”. Używane jest do testowania, do ponownego uruchomienia po poprawce oraz do zadań jednorazowych.
  • Zdarzenie. Dzieje się coś, na co potok danych został zaprogramowany do oczekiwania — w folderze pojawia się nowy plik, na temacie Kafka ląduje wiadomość lub inny potok danych kończy się pomyślnie.

Planowanie wsadowe i polski kalendarz świąt

Zaplanowane potoki danych są zarządzane przez część platformy zwaną Schedulerem. Harmonogramy zapisywane są w formacie cron, od dawna ustanowionym i bardzo zwięzłym sposobie opisywania powtarzających się godzin. Wyrażenie cron to pięć pól — minuta, godzina, dzień miesiąca, miesiąc, dzień tygodnia. Na przykład 0 2 * * 1-5 oznacza „w minucie 0 godziny 2, każdego dnia miesiąca, każdego miesiąca, w dni tygodnia od 1 do 5” — innymi słowy, o 2:00 w dni robocze. Istnieją także przyjazne skróty: @daily, @hourly i @monthly.

DataFlow AI dodaje coś specyficznego dla swojego polskiego klienta: kalendarz polskich dni wolnych od pracy. Wiele raportów biznesowych nie powinno się uruchamiać w dni świąteczne — nie ma świeżej aktywności biznesowej do przetworzenia, a uruchamianie mimo to może wytworzyć mylące „zerowe” dane. Scheduler DataFlow AI rozumie oficjalne polskie dni wolne od pracy zdefiniowane przez prawo znane jako Ustawa o dniach wolnych od pracy: Nowy Rok, Trzech Króli (6 stycznia), Poniedziałek Wielkanocny, Święto Pracy, Święto Konstytucji 3 Maja, Boże Ciało, Wniebowzięcie (15 sierpnia), Wszystkich Świętych (1 listopada), Święto Niepodległości (11 listopada) oraz Boże Narodzenie (25–26 grudnia).

Aby z niego skorzystać, dodajesz specjalny znacznik !PL_HOLIDAY na końcu wyrażenia cron. Tak więc 0 2 * * 1-5 !PL_HOLIDAY oznacza „o 2:00 w dni robocze — ale pomiń polskie dni wolne od pracy”. Harmonogramy domyślnie korzystają ze strefy czasowej Europe/Warsaw.

   0 2 * * 1-5 !PL_HOLIDAY
   │ │ │ │ │   └── skip official Polish public holidays
   │ │ │ │ └────── day of week: 1–5 (Monday to Friday)
   │ │ │ └──────── month: every
   │ │ └────────── day of month: every
   │ └──────────── hour: 02
   └────────────── minute: 00

Potoki danych zależne od innych potoków danych

Potoki danych mogą być również łączone w łańcuchy: potokowi B można polecić, aby poczekał, aż potok A zakończy się pomyślnie, zanim się uruchomi. Jest to opisane w jego własnym rodzaju przepisu (kind: PipelineDependency). Każda zależność określa, na który potok danych czeka, jaki warunek liczy się jako gotowość (sukces lub sukces-albo-pominięcie) oraz maxWaitMinutes — jak długo czekać, zanim się podda. Aby uniknąć problemu, w którym wiele potoków danych budzi się dokładnie w tej samej chwili i przeciąża systemy (problem o przezwisku stado tętniące, ang. thundering herd), scheduler może dodać małe losowe opóźnienie zwane jitterem, rozkładając starty w czasie.


Etap 4 — Jak kroki są porządkowane: silnik wykonawczy DAG

Gdy potok danych zostaje wyzwolony, kontrolę przejmuje część platformy zwana Silnikiem Potoków Danych. Jego pierwszym zadaniem jest zamienienie płaskiej listy węzłów i krawędzi w przepisie na plan wykonawczy — a tym planem jest DAG.

Jak wyjaśniono w Czym jest ETL?, DAG (Skierowany Graf Acykliczny) to jednokierunkowy schemat blokowy bez pętli. Komponent, który go buduje, Konstruktor DAG, robi trzy ważne rzeczy:

  1. Ustala zależności. Czytając krawędzie, dowiaduje się, że na przykład Aggregator nie może zacząć się, dopóki Filter nie skończy, ponieważ Filter go zasila.
  2. Sprawdza pętle. Używając dobrze znanej metody zwanej sortowaniem topologicznym (czasami algorytm Kahna), potwierdza, że nie ma cykli. Gdyby przepis przypadkowo zawierał pętlę, uruchomienie zostałoby tutaj odrzucone, zamiast działać w nieskończoność.
  3. Znajduje kroki, które mogą być uruchamiane obok siebie. Jeśli dwie gałęzie potoku danych nie zależą od siebie, mogą być uruchamiane równolegle — w tym samym czasie — co jest szybsze niż wykonywanie wszystkiego jedno po drugim.

Gdy DAG jest zbudowany, silnik wykonuje węzły w kolejności topologicznej: węzeł uruchamia się dopiero po tym, jak skończy każdy węzeł go zasilający. Niezależne węzły uruchamiają się razem.

Ile uruchamia się naraz

Uruchamianie rzeczy równolegle jest potężne, ale musi być ograniczone, aby platforma nie przeciążyła samej siebie ani systemów źródłowych. DataFlow AI używa trzech konfigurowalnych limitów:

LimitWartość domyślnaCo kontroluje
PIPELINE_MAX_PARALLEL_NODES8Ile węzłów jednego uruchomienia potoku danych może być wykonywanych w tym samym czasie.
PIPELINE_MAX_CONCURRENT_EXECUTIONS20Ile odrębnych uruchomień potoków danych obsługuje jedna instancja silnika naraz.
PIPELINE_EXECUTION_TIMEOUT_SECONDS3600Ogólny limit czasu; uruchomienie przekraczające jedną godzinę jest anulowane.

Śledzenie postępu na żywo

Podczas gdy DAG się wykonuje, silnik nieprzerwanie raportuje postęp. Dla każdego węzła odnotowuje status (WAITING, RUNNING lub COMPLETED), ile wierszy weszło do (rowsIn), ile wyszło z (rowsOut) oraz jak długo to trwało (durationMs). Dla całego potoku danych raportuje ogólny procent postępu, który węzeł jest obecnie aktywny, bieżące sumy odczytanych, zapisanych i odrzuconych wierszy oraz szacowany czas zakończenia. Te informacje to to, co widzisz aktualizujące się na żywo na ekranie Monitora, gdy uruchomienie się rozwija.


Etap 5 — Jak kroki wykonują swoją pracę: transformacje i push-down SQL

Każdy węzeł transformacji wykonuje swoje zadanie na jeden z dwóch bardzo różnych sposobów, a platforma sprytnie wybiera między nimi.

Typy transformacji

Węzły transformacji — expression, filter, aggregator, joiner, router, sorter, union oraz sequence_generator dla kluczy zastępczych — każdy z nich wykonuje jedno dobrze zdefiniowane zadanie przekształcania, dokładnie tak, jak opisano w Czym jest ETL?. Węzły expression i filter oceniają swoją logikę przy użyciu albo SQL, albo małego języka wyrażeń zwanego SpEL (Spring Expression Language — zwięzły sposób zapisywania warunków takich jak rowCount > 0).

Push-down SQL — wysyłanie pracy do danych

Oto jeden z najważniejszych pomysłów DataFlow AI. Przenoszenie dużych ilości danych przez sieć jest powolne i kosztowne. Dlatego, gdzie tylko możliwe, platforma nie przeciąga danych na zewnątrz, aby je przekształcić. Zamiast tego używa swojego Silnika SQL Push-Down.

Silnik SQL Push-Down przepisuje twoje kroki transformacji jako natywny SQL — własny język bazy danych — i wysyła tę krótką instrukcję do bazy danych, polecając bazie danych, aby sama wykonała pracę, tam gdzie dane już się znajdują. Dane nigdy nie podróżują.

Aby to zrobić, musi tłumaczyć na własny dialekt SQL każdej bazy danych, ponieważ żadne dwie bazy danych nie mówią identycznie po SQL (jedna pisze COALESCE, inna pisze NVL, dla tego samego pomysłu). Silnik używa techniki zwanej wzorcem odwiedzającego ASTAbstract Syntax Tree (Abstrakcyjne Drzewo Składniowe) będąc ustrukturyzowaną, drzewiastą reprezentacją transformacji, którą można czysto przepisać dla każdego celu. Obsługuje 8 dialektów: Teradata, Snowflake, PostgreSQL, SQL Server, Oracle, SAP HANA, Databricks (Spark SQL) oraz Sybase ASE.

Silnik decyduje się na użycie push-down, gdy warunki temu sprzyjają. Najwyraźniejszy przypadek to sytuacja, gdy źródło i miejsce docelowe to ta sama baza danych — wtedy cała transformacja może się odbyć wewnątrz tego jednego systemu, a dane w ogóle go nie opuszczają. Push-down jest również wybierany, gdy źródłowa baza danych obsługuje potrzebne funkcje SQL (filtry, grupowanie, złączenia, funkcje okienkowe) oraz gdy szacowana ilość danych jest duża — powyżej konfigurowalnego progu, domyślnie 100 000 wierszy. Nie jest używany dla typów węzłów specyficznych dla strumieniowania, którymi zajmuje się inny silnik. Platforma podaje, że potrafi zepchnąć w dół ponad 90% pracy transformacyjnej w typowych potokach analitycznych.

   WITHOUT push-down                      WITH push-down
   ─────────────────                      ──────────────
   Database  ──millions of rows──▶        Database  ◀──short SQL instruction──
             DataFlow transforms                    Database transforms itself
             ──millions of rows──▶                  ──only the small result──▶
             Destination                            Destination
   (slow: data crosses the network)       (fast: only the instruction travels)

Wsadowy silnik obliczeniowy — Spark na Dataproc

Gdy pracy nie da się zepchnąć do bazy danych — na przykład przy złączaniu tabeli bazy danych z folderem plików lub gdy transformacja jest zbyt złożona — DataFlow AI przetwarza dane sam, używając Apache Spark, silnika zaprojektowanego do przemielania bardzo dużych zbiorów danych poprzez rozłożenie pracy na wiele komputerów naraz.

DataFlow AI uruchamia Spark na Dataproc Serverless, usłudze Google Cloud, która dostarcza moc obliczeniową Spark na żądanie — gdziekolwiek od 4 do 500 maszyn roboczych — bez żadnych klastrów do zarządzania. Zawiera optymalizacje takie jak Adaptive Query Execution, które pozwala Sparkowi dostosować swój plan w połowie uruchomienia na podstawie tego, co faktycznie widzi w danych.


Wszystko powyżej opisuje uruchomienie wsadowe — zaplanowane zadanie, które przetwarza fragment danych i się zatrzymuje. Potoki strumieniowe działają inaczej: uruchamiają się nieprzerwanie i przetwarzają każdy rekord w ciągu sekund.

Potoki strumieniowe są wykonywane przez Apache Flink (wersja 1.18/1.19), silnik zbudowany specjalnie do nigdy niekończących się przepływów danych. DataFlow AI uruchamia Flink na usłudze Kubernetes Google Cloud. Flink wnosi kilka możliwości, których przetwarzanie wsadowe nie potrzebuje:

  • Okna. Ponieważ strumień nigdy się nie kończy, nie możesz „zsumować tego wszystkiego” — nie ma końca. Zamiast tego grupujesz zdarzenia w okna czasu. Okno przeskakujące (tumbling) to stały, nienakładający się wycinek (np. co 5 minut); okno przesuwne (sliding) się nakłada; okno sesji grupuje serie aktywności rozdzielone przerwami.
  • Przetwarzanie według czasu zdarzenia ze znacznikami wodnymi. Rekordy czasami przybywają lekko poza kolejnością. Flink śledzi czas zdarzenia (kiedy coś faktycznie się wydarzyło, a nie kiedy przybyło) i używa znaczników wodnych — markerów, które mówią „wierzymy, że widzieliśmy już wszystko aż do tej chwili” — aby zdecydować, kiedy okno jest kompletne.
  • Punkty kontrolne. Okresowo (domyślnie co 60 sekund) Flink zapisuje kompletny zrzut swojego stanu w toku do chmurowego magazynu. Nazywa się to punktem kontrolnym. Jeśli zadanie się zawiesi, restartuje od ostatniego punktu kontrolnego i niczego nie traci — gwarancja znana jako przetwarzanie dokładnie raz (exactly-once), oznaczająca, że każdy rekord jest przetwarzany raz i tylko raz, nigdy nie pominięty i nigdy nie policzony podwójnie.

Kanał zmian — Debezium CDC

Potok strumieniowy, który utrzymuje kopię bazy danych zsynchronizowaną, potrzebuje kanału na żywo z każdą zmianą. Jak wyjaśniono w Czym jest ETL?, ten kanał jest wytwarzany przez przechwytywanie zmian danych (CDC), a DataFlow AI zapewnia go za pośrednictwem Debezium.

Debezium odczytuje wewnętrzny dziennik transakcji każdej źródłowej bazy danych i zamienia każde wstawienie, aktualizację i usunięcie w wiadomość, publikowaną na temacie Kafka. Każda wiadomość niesie ze sobą obraz wiersza „przed” i „po”, dzięki czemu potoki danych w dół mogą zobaczyć dokładnie, co się zmieniło. Pięć obsługiwanych baz danych, z ich typowymi opóźnieniami od końca do końca, to:

Baza danychJak CDC odczytuje zmianyTypowe opóźnienie
OracleOdczytuje dzienniki redo za pomocą LogMinerponiżej 5 sekund
PostgreSQLOdczytuje dziennik write-ahead (replikacja logiczna)poniżej 2 sekund
SQL ServerOdczytuje natywne tabele CDC SQL Serveraponiżej 5 sekund
MySQLOdczytuje dziennik binarny (binlog)poniżej 2 sekund
MongoDBOdczytuje strumienie zmian MongoDBponiżej 3 sekund

Funkcja specyficzna dla telekomunikacji: dekodowanie Rekordów Szczegółów Połączeń

DataFlow AI zawiera jedną funkcję strumieniową zbudowaną specjalnie dla Polkomtela: dekoder Rekordów Szczegółów Połączeń (CDR). Sprzęt sieci telekomunikacyjnej zapisuje CDR-y w zwartym formacie binarnym zwanym ASN.1 (przy użyciu reguł kodowania znanych jako BER/DER). Nie jest to czytelne dla człowieka ani rozumiane przez zwykłe narzędzia.

DataFlow AI dostarcza zbudowany do tego celu dekoder, napisany w języku programowania Kotlin, który odczytuje ten format binarny i tłumaczy go na normalne, czytelne wiersze — wyciągając pola takie jak numery telefonów dzwoniącego i wybieranego, czas trwania połączenia, wolumen danych oraz godzina. Rozumie formaty rekordów zdefiniowane przez międzynarodowy standard 3GPP TS 32.298, obejmujące zwykłe połączenia, SMS-y, sesje danych oraz nowoczesną telefonię voice-over-LTE. Zdekodowane rekordy są zapisywane jako pliki Parquet (wydajny kolumnowy format plików), z przepustowością około miliona CDR-ów na minutę.

Mówiąc prościej

Strumieniowanie = potok danych, który nigdy się nie zatrzymuje. Flink to silnik, który go uruchamia; okna to sposób, w jaki grupuje nieskończony przepływ na policzalne kawałki; punkty kontrolne to jego zrzuty bezpieczeństwa; Debezium to kanał na żywo zmian bazy danych, który go zasila. Dekoder CDR to specjalny tłumacz, który zamienia zagadkowe binarne rekordy połączeń sieci telekomunikacyjnej w zwykłe, czytelne dane.


Etap 7 — Gdy coś pójdzie nie tak: obsługa błędów i samonaprawianie

W prawdziwym świecie rzeczy zawodzą. Połączenie sieciowe się zrywa; baza danych jest na chwilę przeciążona; plik jest chwilowo zablokowany. Dobra platforma ETL spodziewa się tego i odzyskuje się płynnie, zamiast po prostu się zawalić. DataFlow AI ma trzy warstwy ochrony.

Ponowna próba z wykładniczym wycofywaniem

Gdy krok zawodzi z przejściowego powodu (chwilowa usterka, a nie prawdziwa wada), silnik po prostu próbuje ponownie. Domyślnie ponawia próbę do 3 razy. Co kluczowe, nie ponawia natychmiast — czeka, a czas oczekiwania rośnie za każdym razem. Nazywa się to wykładniczym wycofywaniem (exponential backoff): opóźnienie z grubsza podwaja się przy każdej próbie. Idea polega na tym, że jeśli baza danych jest na chwilę przeciążona, ponowne walenie w nią natychmiast tylko by pogorszyło sytuację; odczekanie chwili — a potem chwili dłuższej — daje jej czas na odzyskanie się.

UstawienieWartość domyślnaZnaczenie
retries3Maksymalna liczba prób ponowienia po awarii przejściowej.
retryDelay300 sekundPoczątkowe opóźnienie przed pierwszą ponowną próbą.
retryBackoffMultiplier2.0Opóźnienie jest mnożone przez to za każdym razem (podwajanie).
retryMaxDelay1800 sekundPułap, dzięki któremu opóźnienie nigdy nie urośnie powyżej 30 minut.

Wyłącznik bezpieczeństwa

Jeśli konkretny system wciąż zawodzi, bez względu na to, ile razy jest ponawiana próba, dalsze walenie w niego jest bezcelowe i szkodliwe. DataFlow AI zapożycza pomysł z elektryki domowej: wyłącznik bezpieczeństwa (circuit breaker).

Tak jak elektryczny wyłącznik bezpieczeństwa „wyskakuje” i odcina zasilanie, gdy wykryje usterkę, wyłącznik bezpieczeństwa DataFlow AI wyskakuje po ustalonej liczbie kolejnych awarii (domyślnie 5) i całkowicie przestaje wysyłać żądania do tego systemu. Po okresie wychładzania (domyślnie 120 sekund) wchodzi w ostrożny stan „półotwarty”, przepuszcza pojedyncze żądanie testowe i — jeśli się powiedzie — zamyka się ponownie i wznawia normalny ruch. To chroni zarówno zawodzący system, jak i resztę platformy przed kaskadą awarii.

Kierowanie błędów i Kolejka Martwych Listów

Czasami problem nie leży w systemie, lecz w samych danych — garstka wierszy jest źle uformowana i nie da się ich przetworzyć. Zamiast porzucać całe uruchomienie dla dobra kilku złych wierszy, DataFlow AI potrafi skierować te wiersze na bok. Każdy węzeł transformacji ma wyjście błędów, a węzeł filter potrafi wysłać odrzucone wiersze do oddzielnego miejsca docelowego. Złe rekordy mogą być zebrane do Kolejki Martwych Listów (Dead Letter Queue) — obszaru przejściowego (termin pochodzi z usług pocztowych, dla listów, których nie da się dostarczyć) — gdzie czekają, z metadanymi opisującymi, co poszło nie tak, aby później zostać zbadanymi i poprawionymi. Dobre wiersze kontynuują bez przeszkód.

Samonaprawianie i diagnoza AI

Gdy uruchomienie naprawdę zawiedzie, AI Copilot DataFlow AI automatycznie wkracza, aby je zdiagnozować. Bada ślad błędu, konfigurację kroku, który zawiódł, kształt danych wejściowych oraz historię podobnych przeszłych awarii. Następnie przedstawia, prostym językiem, najbardziej prawdopodobną przyczynę źródłową, dowody na to wnioskowanie oraz sugerowaną poprawkę krok po kroku — czasami zawierającą poprawiony fragment YAML lub SQL.

Warto być tu precyzyjnym: w obecnej wersji „samonaprawianie” oznacza powyższe mechanizmy ponawiania prób i wyłącznika bezpieczeństwa, plus tę diagnozę AI. Planowana jest przyszła możliwość zwana AI Auto-Heal, w której Copilot wykrywałby powtarzające się awarie i automatycznie stosował poprawkę po zatwierdzeniu jej przez człowieka — ale w obecnym wydaniu poprawkę nadal stosuje człowiek.


Etap 8 — Sprawdzanie wyniku: silnik jakości danych

Wytworzenie danych nie wystarcza; dane muszą również być godne zaufania. Po (i podczas) uruchomieniu DataFlow AI silnik jakości danych sprawdza dane względem zdefiniowanych przez ciebie reguł.

Zestaw reguł jest dołączany do zbioru danych za pomocą jego własnego rodzaju przepisu (kind: DataQualityRuleSet), a reguły są oceniane automatycznie za każdym razem, gdy potok danych się uruchamia. Istnieje 10 wbudowanych typów reguł:

Typ regułyCo sprawdza
NOT_NULLKolumna nigdy nie jest pusta (lub pusta nie częściej niż dozwolony procent).
UNIQUEKolumna — lub kombinacja kolumn — nie ma zduplikowanych wartości.
RANGEWartość liczbowa lub data mieści się między minimum a maksimum.
REGEXWartość tekstowa pasuje do wymaganego wzorca — używane na przykład do sprawdzenia, czy PESEL lub numer telefonu jest poprawnie uformowany.
REFERENTIALKażda wartość w jednej tabeli istnieje również w innej — na przykład identyfikator klienta każdego zamówienia jest prawdziwym klientem.
CUSTOM_SQLNiestandardowa kontrola, którą piszesz sam; musi zwrócić zero wierszy, aby przejść.
COMPLETENESSCo najmniej minimalna proporcja kolumny jest wypełniona.
CONSISTENCYObowiązuje reguła międzykolumnowa — na przykład data końcowa nigdy nie jest wcześniejsza niż data początkowa.
FRESHNESSDane są aktualne — ich najnowszy znacznik czasu jest nie starszy niż dozwolony wiek.
ANOMALYMiara statystyczna nie odchyliła się dziwnie od swojej historycznej normy.

Każda reguła ma wagę (krytyczna, wysoka lub średnia) i może być oznaczona przez blockPipeline, co oznacza, że niespełnienie tej reguły zatrzymuje potok danych, zamiast jedynie ostrzegać. Silnik prowadzi również profil statystyczny każdego zbioru danych — liczby wartości pustych i odrębnych, minimum i maksimum, średnią, odchylenie standardowe, histogram rozkładu wartości oraz najczęstsze wartości — i porównuje każde nowe uruchomienie z tą historią, aby wypatrzyć dryf. Na koniec zwija wszystko w pojedynczy wynik jakości od 0 do 100, dzięki czemu każdy może na pierwszy rzut oka ocenić niezawodność zbioru danych.

Reguła ANOMALY oraz wykrywanie dryfu używają prostej, dobrze zrozumianej statystyki: wartość jest oznaczana, jeśli leży kilka odchyleń standardowych od swojej historycznej średniej (odchylenie standardowe będąc standardową miarą tego, jak rozproszony jest zbiór liczb). To uczciwe statystyczne wykrywanie anomalii porównujące dzisiejsze dane z prawdziwym historycznym punktem odniesienia — a nie zgadywanie.


Składając to wszystko razem

Oto, wreszcie, kompletna podróż pojedynczego uruchomienia potoku danych, z nazwaną odpowiedzialną częścią platformy na każdym kroku:

  WRITTEN     The pipeline DSL (YAML) describes nodes and edges.

  CHECKED     The recipe is validated against the JSON Schema.

  TRIGGERED   The Scheduler fires it — cron time (Polish-holiday-aware),
     │        a manual Run, or an event.

  PLANNED     The Pipeline Engine's DAG Builder orders the nodes,
     │        rejects loops, and finds steps that can run in parallel.

  EXECUTED    Each node runs. The Push-Down SQL Engine sends work into
     │        the database where it can; Spark on Dataproc handles the
     │        rest; Flink + Debezium handle streaming and CDC.

  WATCHED     Per-node row counts, status, and progress stream live
     │        to the Monitor screen.

  PROTECTED   Failures are retried with exponential backoff; the
     │        circuit breaker guards failing systems; bad rows are
     │        routed to a Dead Letter Queue; the AI Copilot diagnoses
     │        outright failures in plain language.

  SCORED      The data quality engine evaluates its 10 rule types and
     │        produces a 0–100 quality score.

  RECORDED    Row counts, duration, outcome, and a new version in Git
              are all saved for history and audit.

Każda część tego modelu istnieje, aby służyć dwóm obietnicom, które składa platforma: że ETL powinno być niezawodne — przetrwając codzienne awarie prawdziwych systemów — oraz przystępne — możliwe do wyjaśnienia, prostym językiem, ludziom, którzy go używają, a nie tylko inżynierom, którzy go zbudowali.

Aby zobaczyć te idee w działaniu poprzez wizualnego projektanta, przejdź do przewodnika po Design Studio; aby dowiedzieć się, jak konkretnie budować potoki strumieniowe, zobacz przewodnik po Strumieniowaniu.

Poprzednia
Stos technologiczny