Korzystanie z RDBMS jako magazynu pozyskiwania zdarzeń

Jeśli używałbym RDBMS (np. SQL Server) do przechowywania danych źródłowych zdarzeń, jak mógłby wyglądać schemat?

Widziałem kilka odmian mówionych w abstrakcyjnym sensie, ale nic konkretnego.

Na przykład, powiedzmy, że mamy podmiot "produkt" , a zmiany w tym produkcie mogą przybrać postać: ceny, kosztu i opisu. Jestem zdezorientowany czy bym:

  1. mieć tabelę" ProductEvent", która zawiera wszystkie pola dla produktu, gdzie każda zmiana oznacza nowy rekord w tej tabeli, plus "kto, co, gdzie, dlaczego, kiedy i jak" odpowiednio. Gdy koszt, cena lub opis są zmieniane, cały nowy wiersz jako dodany do reprezentowania produktu.
  2. przechowywać koszt, cenę i opis produktu w osobnych tabelach połączonych z tabelą produktu za pomocą relacji klucza obcego. Gdy pojawią się zmiany w tych właściwościach, Zapisz nowe wiersze z odpowiednio WWWWWH.
  3. przechowuj WWWWWH, plus serializowany obiekt reprezentujący Zdarzenie, w tabeli "ProductEvent" , oznacza to, że samo zdarzenie musi zostać załadowane, zdeserializowane i ponownie odtworzone w kodzie mojej aplikacji w celu ponownego zbudowania stanu aplikacji dla danego produktu.

Szczególnie martwię się o opcję 2 powyżej. Biorąc pod uwagę skrajność, tabela produktów byłaby prawie jedna tabela na właściwość, gdzie załadowanie stanu aplikacji dla danego produktu wymagałoby załadowania wszystkich zdarzeń dla tego produktu z każdej tabeli zdarzeń produktu. Ta eksplozja nie pachnie mi dobrze.

I 'm sure" it zależy "i chociaż nie ma jednej "poprawnej odpowiedzi", staram się wyczuć, co jest akceptowalne, a co jest całkowicie nie do przyjęcia. Jestem również świadomy, że NoSQL może pomóc tutaj, gdzie zdarzenia mogą być przechowywane na zagregowanym korzeniu, co oznacza tylko pojedyncze żądanie do bazy danych, aby uzyskać zdarzenia do odbudowy obiektu, ale nie używamy w tej chwili bazy danych NoSQL, więc mam ochotę na alternatywy.

Author: ROMANIA_engineer, 2011-08-15

4 answers

Magazyn zdarzeń nie powinien wiedzieć o konkretnych polach lub właściwościach zdarzeń. W przeciwnym razie każda modyfikacja modelu spowodowałaby konieczność migracji bazy danych(tak jak w staromodnym uporczywym stanie). Dlatego w ogóle nie polecałbym opcji 1 i 2.

Poniżej znajduje się schemat zastosowany w Ncqrs . Jak widać, tabela "zdarzenia" przechowuje Powiązane Dane jako CLOB(tj. JSON lub XML). Odpowiada to twojej opcji 3 (tylko, że tam nie jest tabelą "ProductEvents", ponieważ potrzebujesz tylko jednej ogólnej tabeli "Events". W Ncqrs mapowanie do zagregowanych korzeni odbywa się za pomocą tabeli "EventSources", gdzie każde źródło zdarzeń odpowiada rzeczywistemu Zagregowanemu korzeniu.)

Table Events:
    Id [uniqueidentifier] NOT NULL,
    TimeStamp [datetime] NOT NULL,

    Name [varchar](max) NOT NULL,
    Version [varchar](max) NOT NULL,

    EventSourceId [uniqueidentifier] NOT NULL,
    Sequence [bigint], 

    Data [nvarchar](max) NOT NULL

Table EventSources:
    Id [uniqueidentifier] NOT NULL, 
    Type [nvarchar](255) NOT NULL, 
    Version [int] NOT NULL

Mechanizm trwałości SQL implementacji Event Store Jonathana Olivera składa się zasadniczo z jednej tabeli zwanej " Commits "z polem BLOB"Payload". Jest to prawie to samo, co w Ncqrs, tylko że serializuje Zdarzenie właściwości w formacie binarnym (który np. dodaje obsługę szyfrowania).

Greg Young zaleca podobne podejście, które zostało szeroko udokumentowane na stronie internetowej Grega .

Schemat jego prototypowej tabeli "zdarzeń" brzmi:

Table Events
    AggregateId [Guid],
    Data [Blob],
    SequenceNumber [Long],
    Version [Int]
 91
Author: Dennis Traub,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-18 13:04:05

Projekt GitHub CQRS.NET ma kilka konkretnych przykładów, jak można zrobić magazyn zdarzeń w kilku różnych technologiach. W momencie pisania tego tekstu jest implementacja w SQL przy użyciu Linq2SQL i SQL schema aby przejść do niego, jest jeden dla MongoDB, jeden dla DocumentDB (CosmosDB, jeśli jesteś na Azure) i jeden za pomocą EventStore (Jak wspomniano powyżej). Usługa Azure oferuje więcej, takich jak Table Storage i Blob storage, które są bardzo podobne do płaskich przechowywanie plików.

Myślę, że głównym punktem jest to, że wszystkie są zgodne z tym samym zleceniem / umową. Wszystkie przechowują informacje w jednym miejscu / kontenerze/tabeli, używają metadanych do identyfikacji jednego zdarzenia z drugiego i "po prostu" przechowują całe zdarzenie tak, jak było - w niektórych przypadkach serializowane, w technologiach pomocniczych, tak jak było. W zależności od tego, czy wybierzesz bazę dokumentów, relacyjną bazę danych, czy nawet plik płaski, istnieje kilka różnych sposobów osiągnięcia tego samego celu zdarzenia store (jest to przydatne, jeśli zmienisz zdanie w dowolnym momencie i stwierdzisz, że potrzebujesz migracji lub obsługi więcej niż jednej technologii pamięci masowej).

Jako programista projektu mogę podzielić się spostrzeżeniami na temat niektórych wyborów, których dokonaliśmy.

Po pierwsze znaleźliśmy (nawet z unikalnymi Uuidami / Guidami zamiast liczb całkowitych) z wielu powodów sekwencyjne identyfikatory występują ze względów strategicznych, więc samo posiadanie identyfikatora nie było wystarczająco unikalne dla klucza, więc połączyliśmy naszą główną kolumnę klucza ID z typem data / object, aby utworzyć jaki powinien być naprawdę (w sensie aplikacji) unikalny klucz. Wiem, że niektórzy mówią, że nie musisz go przechowywać, ale to zależy od tego, czy jesteś zielony, czy musisz współistnieć z istniejącymi systemami.

Trzymaliśmy się jednego kontenera / tabeli/kolekcji ze względu na konserwowalność, ale bawiliśmy się oddzielną tabelą dla każdego obiektu/obiektu. Okazało się, że w praktyce oznacza to, że aplikacja potrzebuje uprawnień "CREATE" (co ogólnie rzecz biorąc nie jest dobrym pomysłem... ogólnie rzecz biorąc, zawsze są wyjątki/ wykluczenia) lub za każdym razem, gdy nowy obiekt/obiekt powstał lub został wdrożony, nowe kontenery/tabele/Kolekcje musiały być tworzone. Okazało się, że było to boleśnie powolne dla rozwoju lokalnego i problematyczne dla wdrożeń produkcyjnych. Możesz nie, ale to było nasze prawdziwe doświadczenie.

Kolejną rzeczą, o której należy pamiętać, jest to, że żądanie wystąpienia akcji X może skutkować wystąpieniem wielu różnych zdarzeń, dzięki czemu poznanie wszystkich zdarzeń generowanych przez polecenie / event / what ever jest przydatne. Mogą one również dotyczyć różnych typów obiektów, np. pchnięcie "Kup" w koszyku może wywołać zdarzenia konta i magazynu. Zużywająca się aplikacja może chcieć wiedzieć to wszystko, więc dodaliśmy CorrelationId. Oznaczało to, że konsument mógł żądać wszystkich zdarzeń podniesionych w wyniku ich żądania. Zobaczysz to w schemacie .

W szczególności z SQL, stwierdziliśmy, że wydajność naprawdę stała się wąskim gardłem, jeśli indeksy i partycje nie były odpowiednio używane. Pamiętaj, zdarzenia muszą być przesyłane strumieniowo w odwrotnej kolejności, jeśli używasz migawek. Wypróbowaliśmy kilka różnych indeksów i okazało się, że w praktyce do debugowania rzeczywistych aplikacji w produkcji potrzebne są dodatkowe indeksy. Ponownie zobaczysz to w schemacie .

Inne metadane w produkcji były przydatne podczas badań opartych na produkcji, znaczniki czasu dały nam wgląd w kolejność, w jakiej zdarzenia były utrzymywane, a nie Podnoszone. To dało nam niektóre pomoc na szczególnie silnie event driven system, który wywołał ogromne ilości zdarzeń, dając nam informacje na temat wydajności rzeczy takich jak sieci i dystrybucji systemów w całej sieci.

 4
Author: cdmdotnet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-06 23:53:02

Cóż, mógłbyś rzucić okiem na Datomic.

Datomic to baza elastycznych, fakty oparte na czasie, obsługa zapytań i połączeń, elastyczna skalowalność i transakcje ACID.

Napisałem szczegółową odpowiedź tutaj

Możesz obejrzeć wykład Stuarta Halloway ' a wyjaśniający budowę Datomic tutaj

Ponieważ Datomic przechowuje fakty w czasie, można go używać do przypadków użycia pozyskiwania zdarzeń i wiele więcej.

 3
Author: kisai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-12 07:31:21

Możliwa podpowiedź to projekt, po którym następuje " powoli zmieniający się Wymiar "(typ=2) powinien pomóc w pokryciu:

  • kolejność zdarzeń zachodzących (za pomocą klucza zastępczego)
  • trwałość każdego stanu (ważny od - ważny do)

Left fold funkcja powinna być również w porządku do wdrożenia, ale trzeba myśleć o przyszłej złożoności zapytań.

 1
Author: Viktor Nakonechnyy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-13 00:06:08