Przetwarzanie strumieni danych

Dane, dane są wszędzie… wszyscy korzystamy intensywnie z różnych cyfrowych usług i w rezultacie coraz więcej serwisów produkuje coraz większe ilości danych. Informacje muszą szybko dotrzeć do właściwych odbiorców, muszą być błyskawicznie przetworzone lub wzbogacone, zdarzenia w jednym systemie powodują wyzwolenie reakcji w innym miejscu. W „czasie rzeczywistym” – co oznacza z minimalnym opóźnieniem.

Kiedy pojawia się dużo danych z jednego lub wielu systemów, automatycznie stajemy przed problemem zapisu tych informacji, ich interpretacji i prezentacji wyników. Jeśli słyszysz o systemach do przetwarzania „strumieni danych”, zwykle problem zapisu dużej ilości danych jest wymieniany jako główny powód do przejścia z tradycyjnych baz danych do platform strumieniowego przetwarzania danych. Ale to nie jest prawda. „Tradycyjne bazy” potrafią przyjąć miliony rekordów w sekundzie (właściwie górny limit nie istnieje). Masz więcej danych?

To co jest prawdziwym wyzwaniem, to dystrybucja danych (także ich bezpieczne przechowanie), wzbogacenie i aktualizacja, odczyt w różnych systemach.

Jak odbywa się przetwarzanie strumieni danych?

System A wykonuje jakąś czynność i rezultatem tej czynności jest informacja. System B bazuje na tych danych, by dostarczyć informację dla użytkownika tego systemu lub przesłać ją do innego systemu. Dla przypomnienia – dzisiaj procesy obsługiwane są przez systemy, które mają budowę modułową, jak taśma produkcyjna w fabryce. Bardzo rzadko jest to wszystkorobiący kombajn.

System A non-stop produkuje więc dane, to jest nasz ‘strumień danych’. System B z różnych przyczyn nie odbiera tych danych bezpośrednio. Po pierwsze nie potrafi. Nie jest tak zaawansowany, by sobie z tym poradzić. Po drugie często potrzebuje danych, które są przetworzone (dane muszą być zagregowane, dołączone inne informacje, niepotrzebne informacje usunięte…). Wymień inne powody.

I tutaj pojawia się pośrednik – „platforma przetwarzania strumieniowego”. Coś, co będzie w stanie odebrać dane, które napływają z systemu A i udostępnić je po przetworzeniu systemowi B. Najczęściej tą platformą jest Kafka. Ale są też inne – na chmurce i takie, które można mieć u siebie. Są też rozwiązania, które jako takie nie służą do odbierania informacji i ich udostępniania, ale zajmują się przetwarzaniem informacji i ich publikacją do platform - skąd mogą być one pobrane przez systemy (np. Apache Flink).

Jak widzisz na symulacji powyżej system, który wysyła dane nazywa się najczęściej w żargonie „producer”. Platforma odbiera te dane i przechowuje w kontenerach, które nazywane są „topikami” (jeśli jest to Kafka) lub kolejkami (jeśli jest to RabbitMQ). Platforma to prosta baza danych a topik czy kolejkę można porównać z tabelą (to w rzeczywistości bardziej log ale to tylko komplikuje zrozumienie czym one są).

Wiadomości, które są wysyłane do topików/kolejek mogą mieć różną postać. Może to być zwykły tekst, może to być XML, JSON.

Wiadomości te są pobierane przez „konsumentów” a po pobraniu nie są kasowane (Kafka) lub mogą być usunięte przez pobierającego (RabbitMQ). Dlaczego nie są kasowane (Kafka)? Konsumentów wiadomości może być wielu, systemy mogą mieć awarie – wiadomości powinny pozostawać dostępne przez określony czas. Jednak po pewnym, określonym dla każdego topiku czasie, zostaną one usunięte z bazy – system się więc nie przepełni wiadomościami.

Taka organizacja wysyłki i odbioru dużej ilości informacji daje nam dużą elastyczność w organizacji systemów, minimalizuje ryzyko utraty danych. Ale gdzie tutaj „przetwarzanie”?

Przetwarzanie danych

W realnym świecie rzadko kiedy przesyłamy dane dalej w niezmienionej postaci. Najczęściej potrzebujemy je zmienić; usunąć niepotrzebne informacje, zagregować lub dodać inne informacje. Np. kiedy e-commerce wysyła wiadomość, że ktoś właśnie złożył zamówienie, chcemy wiedzieć kim jest ten klient i być może także uaktualnić stan punktów klienta, jeśli jest on uczestnikiem naszego programu lojalnościowego. Więc przykład bardziej realnej architektury może mieć postać:

W takiej architekturze system, zwany „producentem”, wysyła informacje do platformy – trafiają do „topika” lub „kolejki”. Wiadomości te muszą zostać przetworzone – chcemy je wzbogacić o inne informacje. Zostają więc one pobrane przez inny proces i uzupełnione. Taką pracę może wykonać Apache Flink lub Kafka Streams. Te moduły odczytują napływające do platformy wiadomości i korzystając z zewnętrznych systemów produkują dane w takich formacie w jakim chcemy je dostarczyć do „konsumenta”. Jeśli była to np. wiadomość, że klient złożył zamówienie to Apache Flink lub Kafka Streams odczyta z zewnętrznej bazy ilość punktów na karcie lojalnościowej klienta, obliczy sumę jego zakupów i tak uzupełnioną wiadomość zapisze do topiku/kolejki nr 2 skąd zostanie ona pobrana przez „konsumenta”.

Dane napływają ciągle, mówimy o „strumieniach”, i są na bieżąco przetwarzane – strumienie nigdy się nie kończą.

Kim jest „consumer”?

Konsument jest odbiorcą informacji. W najprostszym scenariuszu może to być aplikacja, która wyświetla wiadomości wysłane przez jakiś system. Wyobraźmy sobie np. ekran, na którym pojawiają się logi z systemów monitorujących ruch w sieci. Więc aplikacje mogą być bezpośrednio konsumentami wiadomości (więcej o tym poniżej). Ale zazwyczaj konsumentem jest warstwa pośrednia między aplikacją a platformą. Taki moduł np. pobiera wiadomości, aktualizuje bazę danych, z której korzysta aplikacja. Słyszał(a)eś, że jest to architektura „event-driven” – zdarzenie opisane w wiadomości, którą wysłał system określony jako „producent” zostało odebrane i zareagowała na niego aplikacja, którą obsługuje „consumer”. Np. sprzedaż produktu w jednym z kanałów sprzedażowych spowodowała aktualizację centralnego zapasu firmy.

A na co to komu?

Jak napisałem na początku artykułu, problem zapisu dużej ilości danych jest wymieniany jako główny powód do przejścia z tradycyjnych baz danych do platform strumieniowego przetwarzania danych. Te rozwiązania rzeczywiście są stworzone do obsłużenia dużej ilości danych. Posługując się dedykowanymi językami i funkcjami możesz też uzyskać pożądany wynik szybciej nawet kiedy ilość danych nie przytłacza. Ale największą zaletą takich rozwiązań jest inna niż tradycyjna architektura systemów.

Po pierwsze możesz rozproszyć przetwarzanie danych i uczynić je bardziej odpornym na awarie. Po drugie można je „skalować” – jeśli obciążenie będzie większe, można dodać kolejne węzły/klastry.

Największą zaletą takiej architektury jest możliwość rezygnacji z centralnej bazy danych. Każda aplikacja może posiadać swoją. Zamiast wysyłać zapytania do zdalnej bazy danych, aplikacje uzyskują dostęp do swoich danych lokalnie, co zapewnia lepszą wydajność, zarówno pod względem przepustowości, jak i opóźnień.

W architekturze warstwowej często wiele aplikacji współużytkuje tę samą bazę danych. Dlatego każda zmiana bazy danych, np. zmiana układu danych w związku z aktualizacją aplikacji lub skalowaniem usługi, musi być skoordynowana. Ponieważ każda aplikacja sterowana zdarzeniami odpowiada za własne dane, zmiany reprezentacji danych lub skalowanie aplikacji wymagają mniejszej koordynacji. Każdy posiada tylko dokładnie to, czego potrzebuje.

Gdzie przetwarzanie strumieniowe a gdzie nie?

Strumieniowe przetwarzanie danych jest właściwą techniką do użycia we wszystkich procesach asynchronicznych – systemy, które nadają wiadomości nie wymagają reakcji zwrotnej systemów, które je odbierają. Np. jeśli prowadzisz firmę przewozową i masz kilka oddziałów, które sprzedają bilety na przejazd. Fakt sprzedaży biletu może być „eventem”, który zostanie przetworzony przez platformę i spowoduje aktualizację dashboard’u, dzięki któremu orientujesz się w aktualnym obłożeniu floty, zaktualizuje punkty klienta w programie lojalnościowym. Architektura ta nie nadaje się jednak do rezerwacji biletów – w takim przypadku musisz użyć centralnego punktu, z którego korzystają systemy rezerwacji (czy to kasy, czy strona internetowa).

Środowisko przetwarzania strumieni danych (nie są to tylko ciągłe „strumienie” o czym niżej) to zazwyczaj proste przetwarzanie danych (choć w dużej skali). Jeśli potrzebujesz bardziej skomplikowanych algorytmów i funkcji, złożonych zapytań do baz danych – Kafka, RabbitMQ czy Flink nie są odpowiednimi narzędziami. Przetwarzanie strumieniowe jest uzupełnieniem innych technik a nie ich zamiennikiem.

Strumieniowe przetwarzanie danych na laptopie

Tak, wyobraź sobie że jest to możliwe. Przetwarzanie strumieniowe może być użyte nie tylko do obróbki ciągłego strumienia danych ale też do pracy z plikami – łączenie informacji z różnych źródeł. Biblioteki do przetwarzania strumieni danych są już dostępne w narzędziach ETL; np. Apache HOP. By skorzystać z Apache Flink nie musisz posiadać serwera czy usługi w chmurze – to środowisko możesz uruchomić na swoim osobistym komputerze. Jeśli tylko posiadasz podstawową umiejętność kodowania, możesz napisać transformację, która przetworzy Twoje dane. Do dyspozycji masz jeszcze kilka innych środowisk.

Uff, dotrwał(a)eś do końca artykułu – to już wszystko!