Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Zamiast przechowywać tylko bieżący stan danych w relacyjnej bazie danych, należy przechowywać pełną serię działań wykonywanych na obiekcie w magazynie typu append-only. Magazyn działa jako system rekordu, którego można użyć do materializowania obiektów domeny. Takie podejście może zwiększyć audytowalność i wydajność zapisu w złożonych systemach.
Ważna
Określanie źródła zdarzeń to złożony wzorzec, który wprowadza znaczące kompromisy. Zmienia sposób przechowywania danych, obsługi współbieżności, rozwijania schematów i stanu zapytania. Migracja do lub z rozwiązania opartego na source'owaniu zdarzeń jest kosztowna, a po przyjęciu wzorca ogranicza przyszłe decyzje projektowe w częściach systemu, które go wykorzystują. Przyjmij sourcing zdarzeń, gdy korzyści, takie jak możliwość audytu i rekonstrukcja historyczna, uzasadniają złożoność wzorca. W przypadku większości systemów i większości części systemu tradycyjne zarządzanie danymi jest wystarczające.
Kontekst i problem
Większość aplikacji współpracuje z danymi. Aplikacja zazwyczaj przechowuje najnowszy stan danych w relacyjnej bazie danych i wstawia lub aktualizuje dane zgodnie z potrzebami. Na przykład w tradycyjnym modelu tworzenia, odczytu, aktualizacji i usuwania (CRUD) aplikacja odczytuje dane z magazynu, modyfikuje je i aktualizuje bieżący stan danych przy użyciu nowych wartości, zazwyczaj przy użyciu transakcji, które blokują dane.
Podejście CRUD jest proste i szybkie w przypadku większości scenariuszy. Jednak w systemach o dużym obciążeniu takie podejście stanowi wyzwanie:
Konflikt zapisu: Ponieważ aktualizacje wymagają cyklów odczytu-modyfikacji-zapisu z blokowaniem na poziomie wiersza, współbieżne zapisy w tej samej encji obniżają wydajność i stają się wąskim gardłem pod wpływem obciążenia.
Możliwość inspekcji: Systemy CRUD przechowują tylko najnowszy stan danych. Jeśli nie zaimplementujesz mechanizmu inspekcji, który rejestruje szczegóły każdej operacji w osobnym dzienniku, utracisz historię danych.
Rozwiązanie
Wzorzec Źródłowy Zdarzeń definiuje podejście do obsługi operacji na danych, które są sterowane sekwencją zdarzeń. Każde zdarzenie jest rejestrowane w składzie danych tylko-dopisującym. Kod aplikacji wywołuje zdarzenia opisujące każdą akcję wykonywaną w obiekcie. Zwykle wysyła zdarzenia do kolejki, w której oddzielny proces, obsługujący zdarzenia, nasłuchuje w kolejce i utrwala zdarzenia w magazynie zdarzeń. Każde zdarzenie reprezentuje logiczną zmianę obiektu, taką jak AddedItemToOrder lub OrderCanceled.
Zdarzenia są utrwalane w magazynie zdarzeń, który służy jako system rekordów lub autorytatywne źródło danych o bieżącym stanie danych. Dodatkowe programy obsługi zdarzeń mogą nasłuchiwać określonych zdarzeń i podejmować działania zgodnie z potrzebami. Na przykład użytkownicy mogą inicjować zadania, które stosują operacje w zdarzeniach do innych systemów lub wykonywać inne skojarzone akcje wymagane do zakończenia operacji. Kod aplikacji, który generuje zdarzenia, jest oddzielony od systemów, które subskrybują zdarzenia.
Każda jednostka w systemie źródłowym zdarzeń ma swój własny strumień zdarzeń, który jest uporządkowaną sekwencją zdarzeń, która rejestruje każdą zmianę tej jednostki. W dowolnym momencie aplikacje mogą odczytywać historię zdarzeń. Aplikacje uzyskują bieżący stan jednostki przez odtworzenie wszystkich zdarzeń w strumieniu. Ten proces jest znany jako ponowne wypełnianie. Może to wystąpić na żądanie, gdy aplikacja obsługuje żądanie.
Aplikacje zazwyczaj implementują zmaterializowane widoki , ponieważ kosztowne jest odczytywanie i odtwarzanie zdarzeń. Zmaterializowane widoki to projekcje tylko do odczytu magazynu zdarzeń zoptymalizowane pod kątem wykonywania zapytań. Na przykład system może zachować zmaterializowany widok wszystkich zamówień klientów używanych do wypełnienia interfejsu użytkownika. Gdy aplikacja dodaje nowe zamówienia, dodaje lub usuwa elementy zamówienia lub dodaje informacje o wysyłce, aplikacja zgłasza zdarzenia, a obsługa zdarzeń aktualizuje zmaterializowany widok.
Na poniższym diagramie przedstawiono przegląd tego wzorca w połączeniu ze wzorcem Rozdzielenia Odpowiedzialności Poleceń i Zapytania (CQRS). Warstwa prezentacji odczytuje dane z oddzielnego magazynu tylko do odczytu i zapisuje polecenia do obsługi poleceń. Programy obsługi poleceń pobierają strumień zdarzeń jednostki z magazynu zdarzeń, uruchamiają logikę biznesową i wypychają nowe zdarzenia do kolejki. Obsługiwacze zdarzeń pobierają zdarzenia z kolejki, wpisują zdarzenia do magazynu zdarzeń, aktualizują magazyn tylko do odczytu lub integrują się z systemami zewnętrznymi.
Pobierz plik programu Visio tej architektury.
Workflow
Poniższy przepływ pracy odpowiada poprzedniemu diagramowi:
Warstwa prezentacyjna wywołuje obiekt, który odczytuje z repozytorium tylko do odczytu. Używa zwracanych danych do wypełnienia interfejsu użytkownika.
Warstwa prezentacji wywołuje programy obsługi poleceń, aby wykonywać akcje, takie jak tworzenie koszyka lub dodawanie elementu do koszyka.
Procedura obsługi poleceń ładuje jednostkę, pobierając strumień zdarzeń z magazynu zdarzeń. Na przykład może pobrać wszystkie zdarzenia koszyka. Odtwarza te zdarzenia względem jednostki w celu odtworzenia jego bieżącego stanu przed wystąpieniem nowej akcji.
Logika biznesowa działa i są wywoływane zdarzenia. W większości implementacji zdarzenia są wypychane do kolejki lub tematu w celu oddzielenia producentów zdarzeń i odbiorców zdarzeń.
Procesory zdarzeń nasłuchują określonych zdarzeń i podejmują odpowiednie działania dla obsługującego. W tym przykładzie programy obsługi zdarzeń podejmują następujące akcje:
Zapisz zdarzenia do magazynu zdarzeń
Zaktualizuj magazyn tylko do odczytu zoptymalizowany pod kątem zapytań
Integracja z systemami zewnętrznymi
Zalety wzorca
Wzorzec określania źródła zdarzeń zapewnia następujące korzyści:
Zdarzenia są niezmienne i można je przechowywać w trybie tylko do dopisywania. Interfejs użytkownika, przepływ pracy lub proces, który inicjuje zdarzenie, może być kontynuowany, a zadania obsługujące zdarzenia mogą być uruchamiane w tle. Poprawia się przepustowość zapisu, szczególnie w warstwie prezentacji, ponieważ zapisy append-only unikają konkurencji o blokady na poziomie wierszy, które tworzą systemy aktualizujące na miejscu.
Zdarzenia to proste obiekty, które opisują akcję wykonywaną wraz z wszelkimi skojarzonymi danymi wymaganymi do opisania akcji reprezentowanej przez zdarzenie. Zdarzenia nie aktualizują bezpośrednio magazynu danych. Programy obsługi zdarzeń pobierają i przetwarzają zarejestrowane zdarzenia, gdy program obsługi jest dostępny, a system może obsłużyć obciążenie. Użyj zdarzeń, aby uprościć implementację i zarządzanie.
Zdarzenia zwykle mają znaczenie dla eksperta domenowego, podczas gdy niedopasowanie obiektowo-relacyjne może sprawiać, że złożone tabele bazy danych stają się trudne do zrozumienia. Tabele to sztuczne konstrukcje reprezentujące bieżący stan systemu, a nie zdarzenia, które występują.
Określanie źródła zdarzenia może zapobiec sytuacji, w której równoczesne aktualizacje będą powodować konflikty, ponieważ eliminuje wymóg bezpośredniej aktualizacji obiektów w magazynie danych. Programy obsługi poleceń przywracają jednostkę ze strumienia zdarzeń, aby wymusić reguły biznesowe przed dołączeniem nowych zdarzeń, więc dwa programy obsługi, które ładują jednocześnie tę samą jednostkę, mogą działać w tym samym stanie.
Na przykład każdy obsługujący widzi pięć pozostałych miejsc, a obaj obsługujący mogą zaakceptować rezerwację. Magazyny zdarzeń dotyczą tego scenariusza przy użyciu optymistycznej kontrolki współbieżności i odrzucają dołączanie, jeśli strumień uległ zmianie od czasu jego odczytu. Po odrzuceniu program obsługi ponownie ładuje jednostkę, ponownie ocenia i ponownie próbuje.
Magazyn zdarzeń tylko do dołączania udostępnia dziennik inspekcji, którego aplikacje mogą używać do monitorowania akcji wykonywanych w magazynie danych. Może on ponownie wygenerować bieżący stan jako zmaterializowane widoki lub projekcje, ponownie odtwarzając zdarzenia w dowolnym momencie i może pomóc przetestować i debugować system.
Wymaganie użycia zdarzeń wyrównywczych w celu anulowania zmian może zapewnić historię odwróconych zmian. Jeśli model przechowuje tylko bieżący stan, ta historia nie istnieje. Możesz również użyć listy zdarzeń do analizowania wydajności aplikacji, wykrywania trendów zachowania użytkowników i uzyskiwania innych przydatnych informacji biznesowych.
Programy obsługi poleceń zgłaszają zdarzenia, a zadania wykonują operacje w odpowiedzi na te zdarzenia. To oddzielenie zadań od zdarzeń zapewnia elastyczność i rozszerzalność. Zadania wiedzą o typie zdarzenia i danych zdarzenia, ale nie o operacji, która wyzwala zdarzenie.
Wiele zadań może obsługiwać każde zdarzenie, dzięki czemu można je łatwo zintegrować z innymi usługami i systemami, które nasłuchują tylko nowych zdarzeń zgłaszanych przez magazyn zdarzeń. Jednak zdarzenia w modelu źródła zdarzeń są zazwyczaj niskiego poziomu i może być konieczne wygenerowanie określonych zdarzeń integracyjnych.
Wskazówka
Określanie źródła zdarzeń jest często łączone ze wzorcem CQRS przez wykonywanie zadań zarządzania danymi w odpowiedzi na zdarzenia i materializowanie widoków z przechowywanych zdarzeń. Ta kombinacja służy do niezależnego skalowania odczytów i zapisów, ponieważ pozyskiwanie zdarzeń tylko do dołączania i projekcje zoptymalizowane pod kątem zapytań działają oddzielnie.
Problemy i zagadnienia
Podczas podejmowania decyzji o zaimplementowaniu tego wzorca należy wziąć pod uwagę następujące kwestie:
Projekt zdarzenia: Zaprojektuj zdarzenia, aby przechwycić intencję biznesową za każdą zmianą oprócz stanu wynikowego. Na przykład w systemie rezerwacji miejsc zdarzenie, które rejestruje dwa miejsca zarezerwowane , jest cenniejsze niż zdarzenie, które rejestruje pozostałe miejsca zmienione na 42. Pierwsze zdarzenie informuje o tym, co się stało. Drugie zdarzenie informuje tylko o stanie wynikowym. Zdarzenia ukierunkowane na stan zmniejszają magazyn zdarzeń do dziennika zmian, który nie ma znaczenia biznesowego. Zdarzenia ukierunkowane na intencje zapewniają bardziej szczegółowe projekcje, znaczące dzienniki inspekcji i elastyczność tworzenia nowych modeli odczytu z zdarzeń historycznych bez konieczności zmieniania środowiska zapisu.
Spójność ostateczna: System jest ostatecznie spójny tylko wtedy, gdy tworzy zmaterializowane widoki lub generuje projekcje danych przez odtworzenie zdarzeń. Istnieje opóźnienie między momentem, gdy aplikacja obsługuje żądanie i dodaje zdarzenia do magazynu zdarzeń, czasem publikacji zdarzeń, a momentem, gdy konsumenci obsługują te zdarzenia. W tym okresie nowe zdarzenia opisujące dalsze zmiany jednostek mogą pojawić się w magazynie zdarzeń. Upewnij się, że klienci rozumieją, że dane są ostatecznie spójne i że system został zaprojektowany pod kątem spójności ostatecznej w tych scenariuszach.
Wersjonowanie zdarzeń: Repozytorium zdarzeń jest stałym źródłem informacji, więc nigdy nie należy aktualizować danych zdarzeń. Jedynym sposobem zaktualizowania encji lub cofnięcia zmiany jest dodanie zdarzenia kompensującego do magazynu zdarzeń. Zdarzenie wyrównywujące to nowe zdarzenie, które odwraca lub poprawia efekt poprzedniego zdarzenia. Na przykład
ReservationCanceledzdarzenie rekompensuje wcześniejszeSeatsReservedzdarzenie. Oryginalne zdarzenie pozostaje w strumieniu, a kompensujące zdarzenie rejestruje, że zostało cofnięte.Ta niezmienność oznacza również, że jeśli usterka generuje nieprawidłowe zdarzenia, te zdarzenia będą trwałe w magazynie. Usunięcie usterki w kodzie aplikacji nie powoduje naprawienia zdarzeń historycznych, dlatego może być również konieczne wyrównyowanie zdarzeń lub upcasterów w celu obsługi nieprawidłowych danych podczas odtwarzania. Jeśli schemat (a nie dane) zapisanych zdarzeń musi ulec zmianie, być może podczas migracji, połączenie istniejących zdarzeń w repozytorium z nową wersją może być trudne.
Można użyć następujących strategii pojedynczo lub w połączeniu:
Deserializacja odporna: Projektuj komponenty odbierające zdarzenia, aby ignorowały nieznane pola i stosowały wartości domyślne dla brakujących pól. Takie podejście obsługuje zmiany addytywne, niełamające się, takie jak dodanie pola opcjonalnego, bez konieczności przekształcania przechowywanych zdarzeń.
Wersjonowanie zdarzeń: Dołącz identyfikator wersji w każdym zdarzeniu, albo jako metadane w otoczeniu zdarzenia, albo jako część nazwy typu zdarzenia. Konsumenci używają wersji, aby wybrać odpowiednią logikę obsługi.
Upcasting: Zarejestruj funkcje transformacji, które konwertują starsze schematy zdarzeń do bieżącego schematu podczas deserializacji. Można połączyć upcastery, aby kod aplikacji musiał obsługiwać tylko najnowszą wersję. Przechowywane zdarzenia pozostają niezmienione, co zachowuje niezmienność.
Migracja wewnętrzna: Przepisanie zdarzeń historycznych na nowy schemat bezpośrednio w magazynie zdarzeń. Takie podejście łamie niezmienność i powinno być ostatecznością, ponieważ podważa ścieżkę audytu.
Porządkowanie zdarzeń: Aplikacje wielowątkowe i wiele wystąpień aplikacji mogą przechowywać zdarzenia w magazynie zdarzeń. Spójność zdarzeń w magazynie zdarzeń i kolejność zdarzeń, które mają wpływ na bieżący stan jednostki, są kluczowe. Dodanie znacznika czasu do każdego zdarzenia może pomóc uniknąć problemów. Innym typowym rozwiązaniem jest dodawanie adnotacji do każdego zdarzenia, które wynika z żądania z identyfikatorem przyrostowym. Jeśli dwie akcje podejmują próbę dodania zdarzeń dla tej samej jednostki w tym samym czasie, magazyn zdarzeń może odrzucić zdarzenie pasujące do istniejącego identyfikatora jednostki i identyfikatora zdarzenia.
Wykonywanie zapytań dotyczących zdarzeń: Nie ma standardowego podejścia ani istniejących mechanizmów, takich jak zapytania SQL, do odczytywania zdarzeń w celu uzyskania informacji. Jedyne dane, które można wyodrębnić, to strumień zdarzeń przy użyciu identyfikatora zdarzenia jako kryteriów. Identyfikator zdarzenia przeważnie wykonuje mapowanie na poszczególne jednostki. Bieżący stan jednostki można określić tylko przez odtworzenie wszystkich zdarzeń, które odnoszą się do niej względem oryginalnego stanu tej jednostki.
Opcje magazynu zdarzeń: Magazyn zdarzeń może być specjalnie utworzoną bazą danych przeznaczoną dla strumieni zdarzeń tylko do dopisywania lub relacyjną lub dokumentową bazą danych z tabelą tylko do dopisywania.
Specjalnie utworzone magazyny zdarzeń zapewniają wbudowaną obsługę zadań, takich jak odczytywanie strumienia według jednostki, optymistyczna współbieżność i migawki.
Relacyjne bazy danych są znane i powszechnie dostępne, ale wymagają samodzielnego tworzenia tych zachowań.
Ponieważ każda jednostka ma własny niezależny strumień zdarzeń, zdarzenie przechowuje partycję naturalnie według identyfikatora jednostki, co upraszcza skalowanie w poziomie lub fragmentowanie w razie potrzeby.
Ważna
Nie myl magazynu zdarzeń z brokerem strumieniowym wiadomości o zdarzeniach. Brokerzy komunikatów, tacy jak Apache Kafka, zwykle nie mają zapytań strumieniowych dla poszczególnych jednostek i optymistycznego zarządzania współbieżnością. Działają one również jako warstwa dystrybucji, aby rozsyłać zdarzenia do projekcji i odbiorców zewnętrznych, ale nie są one zamiennikiem magazynu zdarzeń.
Ponowne tworzenie stanu jednostki: Długość każdego strumienia zdarzeń wpływa na sposób zarządzania i aktualizowania systemu. Jeśli strumienie są duże, odtwarzanie każdego zdarzenia w celu ponownego uruchomienia jednostki staje się kosztowne zarówno pod względem czasu, jak i zasobów obliczeniowych. Aby zmniejszyć ten koszt, utwórz migawki w określonych interwałach, takich jak każde N zdarzeń. Migawka to serializowana reprezentacja stanu jednostki w określonym punkcie w strumieniu zdarzeń. Aby ponownie uwodnić jednostkę, załaduj najnowszą migawkę, a następnie odtwórz tylko zdarzenia, które występują po niej, zamiast odtwarzać cały strumień od początku. Po wybraniu częstotliwości migawek zrównoważ koszty magazynowania migawek względem czasu zapisanego podczas ponownego wypełniania.
Uwaga / Notatka
Zrzuty to optymalizacja, a nie zastąpienie strumienia zdarzeń. Strumień zdarzeń pozostaje wiarygodnym źródłem, z którego można w dowolnym momencie ponownie wygenerować zrzuty.
Obsługa konfliktów: Optymistyczna kontrola współbieżności zapobiega konfliktowi zapisów w tym samym strumieniu zdarzeń, ale aplikacja musi nadal obsługiwać konflikty obejmujące wiele jednostek. Na przykład zdarzenie wskazujące zmniejszenie zapasów może pojawić się w magazynie danych, gdy klient składa zamówienie na ten przedmiot. Zaprojektuj system tak, aby uzgodnił te sytuacje, na przykład doradzając klientowi lub tworząc zamówienie wsteczne.
Wymagania dotyczące idempotentności: Dostarczanie zdarzeń do odbiorców zazwyczaj następuje co najmniej raz, więc odbiorcy mogą odbierać to samo zdarzenie więcej niż raz. Programy obsługi zdarzeń muszą być idempotentne, więc przetwarzanie zduplikowanego zdarzenia nie zmienia wyniku. Jeśli na przykład wiele wystąpień procesu konsumenckiego obsługującego zdarzenia rezerwacji miejsc działa w celu zachowania liczby dostępnych miejsc, zduplikowane zdarzenie rezerwacji musi spowodować tylko jedno pomniejszenie. Bez idempotencji projekcje oddalają się od strumienia zdarzeń, a efekty uboczne, takie jak płatności lub powiadomienia, są wywoływane więcej niż raz. Śledź ostatni przetworzony numer sekwencji zdarzeń dla każdego konsumenta i pomiń duplikaty, lub zaprojektuj mutacje stanu, które są z natury bezpieczne do powtórzenia.
Logika cykliczna: Należy pamiętać o scenariuszach, w których przetwarzanie jednego zdarzenia wymaga utworzenia jednego lub kilku nowych zdarzeń. Ta sekwencja może spowodować nieskończoną pętlę.
Testowanie: Określony styl testowania najlepiej pasuje do systemów opartych na zdarzeniach. Skonfiguruj przeszłe zdarzenia, wydaj polecenie i sprawdź nowe utworzone zdarzenia. Podejście given-when-then testuje logikę biznesową bez użycia baz danych, kolejek ani projekcji. Jednak potrzebne są również testy integracyjne dla projekcji, zachowania idempotentności oraz ścieżek ewolucji schematu, co zwiększa powierzchnię testowania w porównaniu z systemami CRUD.
Dane osobowe i zgodność z przepisami: Niezmienna, tylko dodawana natura magazynu zdarzeń jest sprzeczna z regulacjami dotyczącymi ochrony danych osobowych, które wymagają usunięcia danych osobowych, takich jak prawo do bycia zapomnianym . Usuwanie zdarzeń wręcz przerywa integralność strumienia, więc projektowanie tego napięcia od samego początku.
Typowym podejściem jest przechowywanie danych osobowych poza magazynem zdarzeń i odwoływanie się do niego za pomocą identyfikatora w wydarzeniach. Takie podejście umożliwia niezależne usuwanie bez wpływu na strumień zdarzeń.
Jeśli nie możesz oddzielić danych osobowych od zdarzeń, użyj rozdrabniania kryptograficznego. Szyfruj dane osobowe w zdarzeniach, używając klucza na podmiot. Usuń klucz, aby uczynić dane nie do odzyskania, pozostawiając strukturę zdarzeń nienaruszoną. Takie podejście zwiększa obciążenie związane z szyfrowaniem dla każdego odczytu i zapisu i wymaga niezawodnego zarządzania kluczami.
Kiedy należy używać tego wzorca
Użyj tego wzorca, gdy:
Chcesz przechwycić intencję, cel lub przyczynę w danych. Można na przykład przechwytywać zmiany w jednostce klienta jako serię określonych typów zdarzeń, takich jak Przeniesiono do domu, Zamknięte konto lub Zmarły.
Należy zminimalizować lub całkowicie uniknąć konfliktowych aktualizacji danych.
Chcesz rejestrować zdarzenia, aby odtworzyć je, aby przywrócić stan systemu, wycofać zmiany lub zachować historię i dziennik inspekcji. Na przykład gdy zadanie składa się z wielu kroków, może być konieczne uruchomienie akcji w celu przywrócenia aktualizacji, a następnie odtworzenie niektórych kroków w celu przywrócenia danych z powrotem do spójnego stanu.
Aplikacja używa już zdarzeń jako naturalnej funkcji jej działania, a określanie źródła zdarzeń wymaga niewielkiego nakładu pracy nad programowaniem lub implementacją.
Należy rozdzielić proces wprowadzania lub aktualizowania danych z zadań wymaganych do zastosowania tych akcji. Zmiana ta może mieć na celu zwiększenie wydajności interfejsu użytkownika (UI) lub przekazywanie zdarzeń innym odbiornikom, które działają, gdy wystąpią zdarzenia. Na przykład można zintegrować system płac z witryną internetową przesyłania wydatków. Zarówno witryna internetowa, jak i system płac wykorzystują zdarzenia zgłaszane przez magazyn zdarzeń w odpowiedzi na dane zaktualizowane w witrynie internetowej.
Masz elastyczność do zmiany formatu zmaterializowanych modeli i danych jednostki, jeśli wymagania ulegną zmianie lub gdy używasz CQRS i musisz dostosować model odczytu lub widoki prezentujące dane.
Używasz CQRS i spójność ostateczna jest akceptowalna, gdy aktualizowany jest model odczytu, lub ponowne nawodnienie danych z strumienia zdarzeń powoduje akceptowalną redukcję wydajności.
Ten wzorzec może nie być odpowiedni w następujących przypadkach:
Systemy mają proste operacje CRUD, które nie wymagają audytowalności, odtwarzania ani historycznej rekonstrukcji stanu. Obciążenie operacyjne magazynu zdarzeń nie jest uzasadnione, jeśli jedynym wymaganiem jest bieżące odczyty i zapisy stanu.
Prototypy, minimalne produkty opłacalne (MVP) lub systemy mają krótkie oczekiwane cykle życia. Inwestycja z góry w projektowanie zdarzeń, strategia ewolucji schematu i infrastruktura projekcji rzadko dają zwrot w tych scenariuszach.
Systemy wymagają spójności i aktualizacji widoków danych w czasie rzeczywistym. Spójność ostateczna między magazynem zdarzeń a projekcjami jest nieodłączna dla określania źródła zdarzeń.
Domeny, w których dane są głównie statyczne lub referencyjne, takie jak tabele odnośników lub wykazy. Ten typ danych zmienia się rzadko i nie korzysta z historii zmian.
Zespoły nie mają doświadczenia w architekturach opartych na zdarzeniach. Określanie źródła zdarzeń zmienia sposób testowania, debugowania i obsługi systemu. Przyjęcie go bez podstawowej wiedzy zwiększa ryzyko antywzorców, które są kosztowne do odwrócenia.
Wskazówka
Określanie źródła zdarzeń nie musi być decyzją typu wszystko albo nic dla całego systemu. Zastosuj go selektywnie do części systemu, które najbardziej przynosi korzyści, takie jak rejestr płatności lub potok przetwarzania zamówień. Użyj tradycyjnej operacji CRUD w przypadku części, gdy złożoność nie jest uzasadniona, na przykład zarządzanie profilami użytkowników lub konfiguracja aplikacji.
Projektowanie obciążeń roboczych
Oceń, jak używać wzorca Event Sourcing w projektowaniu obciążenia, aby spełnić cele i zasady opisane w filarach platformy Azure Well-Architected Framework. Poniższa tabela zawiera wskazówki dotyczące tego, jak ten wzorzec obsługuje cele poszczególnych filarów.
| Filar | Jak ten wzorzec obsługuje cele filaru |
|---|---|
| Decyzje projektowe dotyczące niezawodności pomagają obciążeniom stały się odporne na awarię i zapewniają, że zostanie ono przywrócone do w pełni funkcjonalnego stanu po wystąpieniu awarii. | Ten wzorzec może ułatwić odtworzenie stanu, jeśli trzeba odzyskać magazyny stanów, ze względu na przechwytywanie historii zmian w złożonych procesach biznesowych. - Partycjonowanie danych - RE:09 Odzyskiwanie po awarii |
| Efektywność wydajności pomaga wydajnie sprostać wymaganiom dzięki optymalizacjom skalowania, danych i kodu. | Ten wzorzec, zwykle w połączeniu z CQRS, odpowiednim projektowaniem domeny oraz strategicznym tworzeniem migawek, może poprawić wydajność pracy z obciążeniami dzięki atomowym operacjom tylko do dołączania i unikaniu blokowania bazy danych przy zapisie i odczycie. - PE:08 Wydajność danych |
Jeśli ten wzorzec wprowadza kompromisy w ramach filaru, rozważ je przed celami innych filarów.
Przykład
System zarządzania konferencjami musi śledzić liczbę ukończonych rezerwacji na konferencji. Śledząc tę liczbę, może sprawdzić dostępne miejsca, gdy potencjalny uczestnik próbuje dokonać rezerwacji. System może przechowywać łączną liczbę rezerwacji na konferencję na co najmniej dwa sposoby:
System może przechowywać informacje o łącznej liczbie rezerwacji jako oddzielnej jednostki w bazie danych, która przechowuje informacje o rezerwacji. Gdy uczestnicy tworzą lub anulują rezerwacje, system zwiększa lub zmniejsza tę liczbę. Takie podejście jest proste w teorii, ale może powodować problemy ze skalowalnością, jeśli duża liczba uczestników próbuje zarezerwować miejsca w krótkim czasie. Na przykład ten wzrost zwykle występuje w ostatnim dniu przed zamknięciem okresu rezerwacji.
System może przechowywać informacje o rezerwacjach i anulowaniach w postaci wydarzeń przechowywanych w repozytorium zdarzeń. Oblicza liczbę dostępnych miejsc, odtwarzając te zdarzenia. Takie podejście może być bardziej skalowalne ze względu na niezmienność zdarzeń. System musi odczytywać tylko dane z magazynu zdarzeń lub dołączać dane do magazynu zdarzeń. Nigdy nie zmienia informacji o wydarzeniach dotyczących rezerwacji i anulowań.
Na poniższym diagramie przedstawiono, jak można używać źródła zdarzeń w celu zaimplementowania podsystemu rezerwacji miejsc w systemie zarządzania konferencjami.
Pobierz plik programu Visio tej architektury.
Workflow
Poniższy przepływ pracy odpowiada poprzedniemu diagramowi:
Interfejs użytkownika wystawia polecenie rezerwowania miejsc dla dwóch uczestników. Osobny program obsługi poleceń obsługuje polecenie . Procedura obsługi poleceń jest elementem logiki, który jest oddzielony od interfejsu użytkownika i jest odpowiedzialny za obsługę żądań opublikowanych jako polecenia.
System tworzy podmiot zawierający informacje o wszystkich rezerwacjach dla konferencji przez odtwarzanie zdarzeń opisujących rezerwacje i anulacje. Ta jednostka jest nazywana
SeatAvailability, i jest zawarta w modelu domeny, który uwidacznia metody wykonywania zapytań i modyfikowania danych w jednostce.Wskazówka
Rozważ optymalizacje, takie jak migawki, aby nie trzeba było powtarzać pełnej listy zdarzeń w celu uzyskania bieżącego stanu jednostki. Migawki zachowują również buforowane kopie jednostki w pamięci.
Procedura obsługi poleceń wywołuje metodę uwidacznianą przez model domeny w celu dokonania rezerwacji.
Jednostka
SeatAvailabilityzgłasza zdarzenie zawierające liczbę miejsc zarezerwowanych. Następnym razem, gdy jednostka zastosuje zdarzenia, użyje wszystkich rezerwacji do obliczenia liczby pozostałych miejsc.System dołącza nowe zdarzenie do listy zdarzeń w repozytorium zdarzeń.
Jeśli użytkownik anuluje miejsce, system wykonuje podobny proces, ale program obsługi poleceń wystawia polecenie, które generuje zdarzenie anulowania siedzenia i dołącza je do magazynu zdarzeń.
System może zapewnić pełną historię lub ślad audytu rezerwacji i anulowań na konferencję, wykorzystując magazyn zdarzeń. Zdarzenia zapisane w magazynie zdarzeń stanowią dokładny zapis. Nie trzeba utrwalać jednostek w żaden inny sposób, ponieważ system może łatwo odtworzyć zdarzenia i przywrócić stan do dowolnego punktu w czasie.
Następne kroki
- Wzorzec CQRS: magazyn zapisu, który zapewnia stałe źródło informacji dla implementacji CQRS, jest zwykle oparty na implementacji wzorca określania źródła zdarzeń. Wzorzec segreguje operacje odczytujące dane w aplikacji z operacji aktualizujących dane przy użyciu oddzielnych interfejsów.
Zasoby społeczności
Event Sourcing, autorstwa Martina Fowlera: Oryginalny opis wzorca z 2005 roku, który ustanowił podstawowe słownictwo.
Dokumenty CQRS (PDF), Greg Young: Ostateczny zasób dotyczący określania źródła zdarzeń i CQRS od praktykującego, który sformalizował oba wzorce.
Powiązane zasoby
Podczas implementowania tego wzorca mogą być również istotne następujące wzorce i wskazówki:
Wzorzec zmaterializowanego widoku: repozytorium danych używane w systemie źródłowania zdarzeń zwykle nie jest przystosowane do wydajnego wykonywania zapytań. Zamiast tego typowym podejściem jest generowanie wstępnie wypełnionych widoków danych w regularnych odstępach czasu lub gdy dane się zmieniają.
Wzorzec wyrównawczej transakcji: system nie aktualizuje istniejących danych w repozytorium źródła zdarzeń. Zamiast tego dodaje nowe wpisy, które zmieniają stan jednostek na nowe wartości. Aby cofnąć zmianę, używa wpisów wyrównywujących, ponieważ nie może odwrócić poprzedniej zmiany. W artykule Wzorzec transakcji kompensującej opisano sposób odwrócenia skutków operacji wykonywanej wcześniej.
Analiza domeny dla mikrousług: w systemach korzystających z projektowania opartego na domenie (DDD) jednostka będąca właścicielem strumienia zdarzeń jest zwykle agregowaniem, granicą spójności, która odbiera polecenia, wymusza reguły biznesowe i emituje zdarzenia.