EventStoreDB: Krótki przegląd zasad pracy z bazą danych
Jako Lead Software Engineer w Innovecs, regularnie dzielę się wiedzą zawodową i spostrzeżeniami z moim zespołem. Niedawno poprowadziłem wykład dla moich współpracowników na temat EventStoreDB i zdałem sobie sprawę, że podstawowe pojęcia, które omówiłem, mogą zainteresować szersze grono odbiorców.Ten artykuł skierowany jest do osób ciekawych Event Sourcingu i zastanawiających się, czy EventStoreDB to odpowiedni wybór dla nich.
Event Sourcing to metoda, w której zamiast przechowywać bieżący stan systemu, zapisuje się wszystkie zmiany w formie zdarzeń, które stanowią główne źródło danych. Podejście to zyskało na popularności około 2005 roku za sprawą artykułu Martina Fowlera na ten temat.
Na czym polega Event Sourcing?
Zamiast przechowywać i na bieżąco aktualizować stan aplikacji, zapisujesz zdarzenia opisujące wprowadzone zmiany. To właśnie zdarzenia stają się kluczowym źródłem informacji. W odróżnieniu od tradycyjnego podejścia, gdzie zapisuje się bieżący stan i modyfikuje go przy każdej zmianie, w Event Sourcing każda zmiana jest rejestrowana jako nowe zdarzenie, a nie jako modyfikacja istniejących danych.
Przykład:
W aplikacji, w której użytkownicy mogą edytować swoje profile, tradycyjne podejście polega na użyciu polecenia „Update” do zmiany istniejących danych w bazie. W przypadku Event Sourcing zamiast „Update” stosuje się „Insert” — dodaje się nowy wpis do dziennika zdarzeń, który odnotowuje wprowadzone zmiany.
Możliwości EventStoreDB
EventStoreDB to baza danych zaprojektowana z myślą o przechowywaniu zdarzeń, które organizowane są w strumienie. Wspiera klasteryzację, co pozwala na jej działanie na wielu węzłach, i jest dostępna zarówno w wersji lokalnej (on-premises), jak i w chmurze. Jest to jedno z najczęściej wykorzystywanych narzędzi do implementacji wzorca Event Sourcing.
Kluczowe funkcje:
- Obsługa streamingu zdarzeń: Możliwość subskrybowania zdarzeń w strumieniach.
- Tworzenie projekcji: Nowe strumienie tworzone na podstawie istniejących danych.
Wbudowane projekcje:
- Grupowanie zdarzeń według kategorii, identyfikatora itd.
- ByCategory: Łączy wszystkie zdarzenia z różnych strumieni w ramach jednej kategorii (np. strumienie account-1, account-2 zostają połączone w jeden strumień account).
Open Source SDK
EventStoreDB wspiera wiele języków programowania, w tym .NET, Java, Python.
Architektura i technologie:
- Zrealizowana w C#.
- Komunikacja za pomocą gRPC (starszy klient TCP nie jest już wspierany).
Zasada działania EventStoreDB
W relacyjnych bazach danych korzysta się z tabel zawierających zmienne wiersze. EventStoreDB przechowuje zdarzenia w formie Append-Only Log (niezmienialnego dziennika).
Niezmienność zdarzeń:
Zdarzenia w strumieniu są niezmienialne (immutable). Choć nie można zmienić zdarzenia, jego skutki można korygować za pomocą nowych zdarzeń.
Przykład:
Jeśli wystawiono fakturę z błędnym adresem („InvoiceIssued”), można dodać dwa nowe zdarzenia: „InvoiceVoided” (anulowanie faktury) oraz nową „InvoiceIssued” z poprawnym adresem. Wszystkie zdarzenia pozostają w dzienniku, ale wynik końcowy jest zgodny z oczekiwaniami.
Strumienie:
Każdy strumień reprezentuje unikalny obiekt. Wszystkie zdarzenia powiązane z konkretnym obiektem domenowym są przechowywane w określonym strumieniu. Strumienie te stanowią source of truth dla obiektu i przechowują pełną historię zmian.
Zarządzanie projekcjami
Projekcje, znane również jako modele widoków (View Models), przekształcają dane ze zdarzeń w czytelny format. Mogą być używane zarówno w modelach odczytu, jak i zapisu.
W EventStoreDB dane ze strumieni można przekształcać w nowe strumienie za pomocą wbudowanych lub niestandardowych projekcji.
- ByCategory: Grupuje zdarzenia według kategorii.
- ByEventType: Zbiera zdarzenia określonego typu (na przykład wszystkie wpłaty na konta).
- ByCorrelationID: Wybiera zdarzenia na podstawie konkretnego Correlation ID.
Niestandardowe projekcje definiuje się za pomocą JavaScriptu. Pozwalają one konfigurować funkcje do przetwarzania zdarzeń oraz format ich transformacji.
javascript
await eventStoreProjectionManagementClient.EnableAsync("$by_category", cancellationToken: stoppingToken);
Zapisywanie i odczytywanie danych
Do zapisywania danych w EventStoreDB używa się metody appendToStream.
Parametry metody:
- Nazwa strumienia (np. account-123). Separator dla kategorii i identyfikatora to domyślnie myślnik.
- Oczekiwana wersja (optional):Jeśli nie zostanie określona, stosowana jest optymistyczna konkurencja.Jeśli strumień jeszcze nie istnieje, używana jest wartość stream revision none.
Przed zapisaniem zdarzenia są serializowane do formatu JSON i konwertowane na tablicę bajtów.
Odczytywanie danych
Odczyt może być wykonywany w kierunku forward (do przodu) lub backward (do tyłu).Dostęp do zdarzeń uzyskuje się na podstawie nazwy strumienia oraz wskazania pozycji (np. start, end lub konkretnej wersji).
Typy subskrypcji w EventStoreDB
Jedną z głównych zalet Event Sourcing jest możliwość obserwowalności. Każda akcja w systemie generuje zdarzenie, które rejestruje dane biznesowe o jej wyniku. Jest to prosta, ale niezwykle potężna funkcja, która umożliwia tworzenie złożonych procesów biznesowych oraz ich podział na mniejsze części łatwiejsze w zarządzaniu.
EventStoreDB realizuje to dzięki funkcji subskrypcji, przypominającej koncepcję „przechwytywania danych o zmianach” (Change Data Capture) w relacyjnych bazach danych. Każde zdarzenie zapisane w bazie danych może inicjować komunikaty, które subskrybenci odbierają i wykorzystują do podejmowania dalszych działań.
Rodzaje subskrypcji:
Volatile Subscriptions
- Szybki dostęp do zdarzeń z minimalnym opóźnieniem.
- Dane dostępne są wyłącznie dla nowych zdarzeń — pominięte zdarzenia nie są dostarczane.
Catch-Up Subscriptions
- Możliwość wskazania pozycji początkowej odczytu.
- Subskrybent samodzielnie zapisuje punkty kontrolne (checkpointy).
Persistent Subscriptions
- Pozycja odczytu przechowywana jest po stronie serwera.
- Guaranteed event delivery.
Wykorzystanie EventStoreDB w systemach
EventStoreDB może służyć jako źródło zdarzeń dla innych baz danych (np. SQL, baz grafowych, wyszukiwarek pełnotekstowych) lub jako operacyjna baza danych dla Twojego systemu.
Możliwości integracji z innymi systemami:
- Subskrybowanie strumieni i zapisywanie danych w kolejkach komunikatów (np. Kafka, RabbitMQ).
- Wykorzystanie projekcji do dostosowania danych do specyficznych potrzeb.
Narzędzia i SDK
Podstawowe pakiety SDK dla .NET:
- EventStore Client GRPC Streams – odczyt i zapis strumieni.
- Persistent Subscription – subskrypcja zmian w strumieniach.
- Projection Management – zarządzanie projekcjami.
Konfiguracja projekcji może być realizowana za pomocą:
- wiersza poleceń,
- plików YAML,
- programowo z wykorzystaniem SDK.
Admin UI
EventStoreDB oferuje wbudowany Admin UI, który znacząco upraszcza zarządzanie strumieniami zdarzeń i projekcjami. Interfejs ten pozwala programistom i administratorom na:
- ręczne tworzenie, przeglądanie i zarządzanie strumieniami zdarzeń,
- definiowanie i testowanie projekcji w czasie rzeczywistym.
Za pomocą Admin UI można:
- monitorować stan systemu,
- usuwać problemy,
- eksperymentować z różnymi modelami zapytań bez potrzeby użycia specjalistycznych narzędzi czy skryptów.
Podsumowując, Event Sourcing to potężna koncepcja, która pozwala nie tylko na przechowywanie pełnej historii zmian w systemie, ale także zapewnia elastyczność i przejrzystość w budowaniu procesów biznesowych. Dzięki możliwości rejestrowania każdego zdarzenia, model ten gwarantuje obserwowalność, skalowalność oraz łatwą adaptację systemu do nowych wymagań.
EventStoreDB, jako jedna z wiodących platform do realizacji Event Sourcing, oferuje intuicyjne narzędzia, bogatą funkcjonalność do pracy ze strumieniami, subskrypcjami i projekcjami, a także wsparcie dla wielu języków programowania. Z tego powodu programiści często wybierają EventStoreDB do tworzenia niezawodnych, skalowalnych i elastycznych systemów.