Analiza przypadków użycia Hazelcast w środowisku rozproszonym

Wykorzystanie Hazelcast w projekcie niesie za sobą nowe wyzwania techniczne, z którymi musieliśmy się zmierzyć. W tym artykule postanowiliśmy omówić najciekawsze z nich. Dowiecie się jak użyć Hazelcasta do komunikacji pomiędzy mikroserwisami w oparciu o eventy oraz jak wygląda inicjalizacja Hazelcasta z różnych źródeł danych.

Inicjalizacja – baza danych. Runtime – zewnętrzny serwis

Nietrudno wyobrazić sobie następującą sytuację – inicjalizacja cache’a ma odbyć się poprzez załadowanie danych z bazy danych, natomiast po zakończeniu inicjalizacji chcemy dociągać dane z zewnętrznego serwisu. Informacja o tym, że inicjalizacja została zakończona powinna być dostępna dla wszystkich członków klastra, dlatego będzie przechowywana w IMap’ie, która została nazwana initMap. Logika ta powinna być wywoływana jednorazowo w momencie, gdy instancja serwisu zostanie uruchomiona i w pełni zainicjalizowana. Przykładowy fragment kodu wyglądałby następująco:

Gdzie metoda load wygląda następująco:

Kod.1. Logika wyzwalająca inicjalizację Hazelcasta

Należy zauważyć, że wykorzystanie wspomnianych wcześniej mechanizmów Hazelcastowych (MapStore, MapLoader) zwalnia nas od odpowiedzialności za synchronizację procesu inicjalizacji. Jeśli kilka instancji serwisu wywoła w tym samym czasie metodę HazelcastInstance.getMap() nie spowoduje to dwukrotnego załadowania danych. Zobaczmy, jak wyglądałaby przykładowa implementacja metody loadAll().

Kod.2. Implementacja metody loadAll() odziedziczonej z interfejsu MapLoader

Jeśli inicjalizacja została zakończona, czytamy z zewnętrznego serwisu. W przeciwnym przypadku wykonujemy zapytanie do bazy danych celem wyciągnięcia danych.

ReadBackupData oraz BackupCount

Do prawidłowego działania aplikacji należy odpowiednio skonfigurować initMap. Parametr backupCount określa liczbę instancji, na której znajdzie się kopia zapasowa initMap. Wartość ta powinna wynosić n – 1, gdzie n to liczba instancji, które razem tworzą klaster. Dodatkowo, należy nadać parametrowi readBackupData wartość true po to, aby umożliwić Hazelcastowi sięganie do lokalnej kopii mapy initMap. Brak tej konfiguracji (lub sytuacja, gdy konfiguracja jest nieprawidłowa) prędzej bądź później będzie skutkować wyjątkiem o treści: cannot make remote call.

ZOBACZ TEŻ:  Analiza dźwięku i czasu pogłosu w pomieszczeniach z wykorzystaniem Python

Kod.3. Fragment kodu przedstawiający konfigurację mapy initMap

Należy zwrócić uwagę, że zdefiniowana mapa initMap posiada podpięty MapLoader. Dzięki takiej konfiguracji, za każdym razem gdy aplikacja uruchamiająca Hazelcasta zostanie na nowo wdrożona na środowisko, odbędzie się inicjalizacja z bazy danych (klucz loaded ma domyślnie wartość false). Jego implementacja wygląda następująco:

Kod.4. Implementacja interfejsu MapLoader dla mapy initMap

Podsumowanie

Zaprezentowany sposób na przełączenie logiki MapLoader/MapStore jest jednym z wielu na rozwiązanie tego problemu. Należy mieć na uwadze, że dostęp do innych struktur danych Hazelcasta z poziomu MapLoader/MapStore może generować potencjalne problemy, np. wystąpienie deadlock’ów. W przedstawionym rozwiązaniu zagrożenie to nie występuje, dzięki czytaniu lokalnej kopii mapy initMap, jednak dzieje się to kosztem spójności danych. W tym przypadku nie jest to aż tak dotkliwe.

Innym sposobem na rozwiązanie problemu mogłoby być wykorzystanie dedykowanej struktury danych com.hazelcast.core.ReplicatedMap, bądź nasłuchiwanie na zmianę wartości mapy initMap i powiązanie tego z logiką zawartą w metodach loadAll()/load().

Zdjęcie główne artykułu pochodzi z unsplash.com.

Zapraszamy do dyskusji

Patronujemy

 
 
More Stories
Nowa biblioteka od Facebooka – RecoilJS. Śniadanie z Programowaniem #39