>_ DevTrendspl

Język

Strona główna

Języki

Sekcje

Frontend Backend Mobilne DevOps AI / ML GameDev Blockchain Systemy wbudowane Bezpieczeństwo
Java

Jak przetwarzać miliardy zdarzeń na sekundę bez zabijania latencji

Wyobraź sobie taką sytuację: musisz sprawdzać transakcje bankowe pod kątem oszustw w czasie rzeczywistym podczas procesu płatności. Masz zaledwie kilka milisekund na podjęcie decyzji. Apache Kafka nieprzerwanie przesyła strumieniowo zdarzenia, ale dla każdego z nich musisz pobrać historię klienta z bazy danych. Jeśli będziesz wysyłać zapytania do tradycyjnego PostgreSQL lub MySQL dla każdej wiadomości, system natychmiast załamie się pod obciążeniem.

To jest częsty impas, z którym spotykają się inżynierowie projektujący systemy o wysokim obciążeniu. Zwykła pamięć podręczna, taka jak Redis, pomaga przyspieszyć odczyty pojedynczych kluczy, ale jeśli chodzi o budowanie złożonej logiki biznesowej i analiz na szczycie strumienia danych, jej możliwości zaczynają być niewystarczające. Zmuszony jesteś łączyć cache, brokerów wiadomości i silniki przetwarzania stron trzecich. W tym momencie warto przyjrzeć się Hazelcast.

Hazelcast łączy rozproszoną pamięć operacyjną i silnik przetwarzania strumieniowego w jednym systemie. Zamiast składać konstrukcję z trzech różnych usług, otrzymujesz ujednoliconą platformę zdolną do pozyskiwania, wzbogacania i analizowania danych w locie.

Co dzieje się wewnątrz platformy

Sercem platformy jest silnik Jet. Odpowiada on za budowanie potoków przetwarzania danych. Jet może równie dobrze pracować ze strumieniami ciągłymi i statycznymi zbiorami danych, takimi jak buckety w Amazon S3 czy tabele w relacyjnej bazie danych.

Metryki wydajności są interesujące. Pojedynczy węzeł Hazelcast może agregować 10 milionów zdarzeń na sekundę, utrzymując latencję w granicach 10 milisekund. Jeśli połączysz serwery w klastry, przepływność wzrasta do miliarda zdarzeń na sekundę.

Aby pisać zapytania do strumieni danych, nie musisz zagłębiać się w niskopoziomowe API Java. Platforma obsługuje standardowy SQL. Możesz napisać znajome zapytanie wobec przychodzącego strumienia danych, połączyć je z tabelą w pamięci operacyjnej i natychmiast przekierować wynik do usługi docelowej.

Tak wygląda łączenie ze źródłami zewnętrznymi. Po wyjęciu z pudełka otrzymujesz zestaw konektorów:

  • Apache Kafka i JMS do pracy z kolejkami
  • Hadoop i Amazon S3 do dostępu do magazynu plików
  • Relacyjne bazy danych poprzez standardowy JDBC
  • Modele w Pythonie do uruchamiania uczenia maszynowego bezpośrednio w potoku

Rozproszona pamięć i koordynacja

Jeśli wyłączysz analizę strumieniową z równania, Hazelcast nadal pozostaje rozproszonym magazynem klucz-wartość. Dane są rozproszone między węzłami klastra jako partycje. Deweloperzy mają dostęp do znanych struktur Java (IMap, IQueue, ITopic), z tą jedyną różnicą, że są rozproszone przez sieć. Wyszukiwanie punktowe po kluczu zajmuje mikrosekundy.

Dla operacji na bazie danych obsługiwane są klasyczne wzorce cache'owania: read-through, write-through i write-behind. Przy użyciu write-behind aplikacja zapisuje dane wyłącznie w pamięci RAM Hazelcast, a platforma asynchronicznie zrzuca je na dysk i do głównej bazy danych. Jeśli relacyjny DBMS tymczasowo przestanie działać, Twoja aplikacja będzie nadal przyjmować żądania bez awarii.

Osobna funkcja to koordynacja mikrousług. Hazelcast może zarządzać rozproszonymi blokadami, generować unikalne sekwencje identyfikatorów i utrzymywać wspólne liczniki. Eliminuje to potrzebę wdrażania i utrzymywania oddzielnego klastra Apache ZooKeeper dla rutynowych zadań synchronizacji.

Jak zbudować i uruchomić projekt

Kod źródłowy projektu jest napisany w Javie. Do budowania ze źródeł wymagany jest JDK 17 lub nowszy. Najłatwiejszy sposób budowania projektu to użycie skryptu Maven Wrapper:

git pull origin master
./mvnw clean package -DskipTests

Pełna kompilacja ze wszystkimi sprawdzeniami może trochę potrwać. Jeśli chcesz szybko zweryfikować lokalne zmiany, użyj flagi -Dquick:

./mvnw clean package -DskipTests -Dquick

Ten parametr wyłącza generowanie Javadoc, sprawdzanie Checkstyle i kompilację modułów pomocniczych.

Sytuacja z testami jest interesująca. Repozytorium zawiera tysiące testów podzielonych na trzy profile:

  • Standardowy profil ./mvnw test uruchamia szybkie testy integracyjne.
  • Profil nocny ./mvnw test -P nightly-build obejmuje wolne testy, których nie można uruchamiać równolegle.
  • Pełny profil ./mvnw test -P all-tests sekwencyjnie uruchamia wszystkie sprawdzenia z użyciem sieci.

Niektóre testy zależą od Dockera. Jeśli Docker nie jest zainstalowany na Twojej maszynie, te testy zakończą się niepowodzeniem. Aby je wyłączyć, użyj parametru -Dhazelcast.disable.docker.tests. Podczas tworzenia Pull Request serwer CI projektu uruchamia pełny zestaw, więc lokalnie wystarczy uruchomić testy tylko dla własnego modułu.

Klientów możesz pisać nie tylko w Javie. Społeczność i firma utrzymują oficjalne biblioteki dla Pythona, Node.js, .NET, C++ i Go.

Licencja i kilka praktycznych niuansów

Kod w repozytorium jest podzielony na dwie części. Rdzeń jest rozpowszechniany na podstawie permisywnej licencji Apache 2.0. Jednak niektóre funkcje enterprise i moduły są chronione przez Hazelcast Community License. Zabrania ona wykorzystywania kodu do tworzenia płatnych usług zarządzanych (Cloud Service Provider), które konkurują z oryginalnym produktem chmurowym firmy.

Drugim punktem są wymagania dotyczące zasobów. Ponieważ wszystkie gorące dane znajdują się w pamięci RAM, będziesz musiał zakupić znaczną ilość pamięci do pracy z dużymi wolumenami. Ponadto w środowisku Java powinieneś zwrócić szczególną uwagę na ustawienia Garbage Collectora, aby uniknąć pauz podczas czyszczenia gigabajtów pamięci. Jednak inżynierowie Hazelcast łagodzą ten problem dzięki pamięci off-heap, przenosząc dane poza stertę Javy.

Kto powinien przyjrzeć się Hazelcast

Platforma dobrze sprawdza się tam, gdzie liczy się reakcja na zdarzenia w czasie rzeczywistym:

  • Zapobieganie oszustwom i scoring w fintech
  • Przetwarzanie telemetrii i sygnałów IoT o wysokiej częstotliwości
  • Obliczanie cen i rabatów w e-commerce w momencie kliknięcia klienta
  • Synchronizacja danych między rozproszonymi centrami danych (replikacja WAN)

Jeśli potrzebujesz tylko prostej pamięci podręcznej dla kilku endpointów, Hazelcast byłby przesadą: prostszy Redis poradziłby sobie z tym zadaniem. Ale jeśli Twój projekt urósł do skali, w której analityka strumieniowa musi przecinać się z rozproszoną pamięcią bez ciągłych wycieczek do magazynu dyskowego, Hazelcast zaoszczędzi Ci miesiące pracy przy tworzeniu rozwiązania.

Powiązane projekty