Dlaczego baza danych jako kolejka tak źle? [Zamknięte]

33

Właśnie przeczytałem ten artykuł i jestem zdezorientowany.

Wyobraźmy sobie 1 aplikację internetową i 1 odrębną aplikację działającą jako „pracownik”, obie współużytkujące tę samą bazę danych .

Och, powiedziałem „dzielenie się” .. ale o czym ostrzega ten artykuł? :

Po czwarte, współdzielenie bazy danych między aplikacjami (lub usługami) jest złą rzeczą. To zbyt kuszące, aby umieścić tam amorficzny stan wspólny i zanim się zorientujesz, będziesz miał ogromnie sprzężonego potwora.

=> nie zgadzam się. W niektórych przypadkach odrębne aplikacje nadal stanowią część tego samego urządzenia, dlatego też pojęcie „problemu z połączeniem” nie ma w tym przypadku sensu.

Kontynuujmy: aplikacja internetowa obsługuje żądania HTTP klientów i może aktualizować w dowolnym momencie niektóre agregacje (termin DDD), generując odpowiednie zdarzenia domeny.
Celem pracownika będzie obsługa tych zdarzeń domeny poprzez przetwarzanie potrzebnych zadań.

Chodzi o to:

Jak dane dotyczące zdarzeń powinny być przekazywane do pracownika?

Pierwszym rozwiązaniem, jak promuje czytany artykuł, byłoby użycie RabbitMQ, będącego doskonałym oprogramowaniem pośredniczącym zorientowanym na wiadomości.

Przepływ pracy byłby prosty:

Za każdym razem, gdy dyno sieciowe generuje zdarzenie, publikuje je za pośrednictwem RabbitMQ, który karmi pracownika.
Wadą byłoby to, że nic nie gwarantuje natychmiastowej spójności między zatwierdzeniem aktualizacji zbiorczej a opublikowaniem zdarzenia, bez radzenia sobie z potencjalnymi błędami wysyłania ... lub problemami sprzętowymi; to kolejny główny problem.

Przykład: Możliwe jest, że zdarzenie zostało opublikowane bez powodzenia aktualizacji zbiorczej ... w wyniku czego zdarzenie reprezentuje fałszywą reprezentację modelu domeny.
Można argumentować, że istnieje globalne XA (zatwierdzanie dwufazowe), ale nie jest to rozwiązanie, które pasuje do wszystkich baz danych lub oprogramowania pośredniego.

Co może być dobrym rozwiązaniem dla zapewnienia tej natychmiastowej spójności? :
IMO, przechowując zdarzenie w bazie danych, w tej samej transakcji lokalnej, co aktualizacja zbiorcza.
Zostanie utworzony prosty asynchroniczny program planujący, który będzie odpowiadał na zapytania dotyczące bieżących niepublikowanych zdarzeń z bazy danych i wysyłał je do RabbitMQ, który z kolei zapełnia pracownika.

Ale po co potrzebować dodatkowego harmonogramu po stronie aplikacji i przy okazji: po co w tym przypadku RabbitMQ?

Dzięki temu rozwiązaniu logiczne wydaje się, że RabbitMQ może być niepotrzebny, szczególnie dlatego, że baza danych jest współdzielona.
Rzeczywiście, bez względu na przypadek, widzieliśmy, że natychmiastowa spójność obejmuje odpytywanie z bazy danych.
Dlaczego więc pracownik nie byłby bezpośrednio odpowiedzialny za tę ankietę?

Zastanawiam się zatem, dlaczego tak wiele artykułów w Internecie z trudem krytykuje kolejkowanie baz danych, jednocześnie promując oprogramowanie pośrednie zorientowane na wiadomości.

Fragment artykułu:

Proste, użyj odpowiedniego narzędzia do pracy: ten scenariusz wymaga systemu przesyłania wiadomości. Rozwiązuje wszystkie problemy opisane powyżej; koniec z odpytywaniem, wydajne dostarczanie wiadomości, nie trzeba usuwać ukończonych wiadomości z kolejek ani żadnego stanu współdzielonego.

I natychmiastowa konsekwencja, zignorowana?

Podsumowując, naprawdę wydaje się, że niezależnie od przypadku, co oznacza, że ​​baza danych jest współdzielona czy nie, potrzebujemy sondowania bazy danych .

Czy przeoczyłem niektóre krytyczne pojęcia?

Dzięki

Mik378
źródło
2
Sondowanie jest rodzajem czerwonego śledzia, ponieważ prawie wszystkie główne bazy danych mają mechanizm asynchronicznego powiadamiania innego procesu, że nadszedł czas, aby wyciągnąć trochę pracy ze stołu.
Blrfl,

Odpowiedzi:

28

Jeśli budujesz prostą aplikację o małym natężeniu ruchu, możesz powiedzieć coś o trzymaniu innego komponentu poza systemem. Jest bardzo prawdopodobne, że nieużywanie magistrali komunikatów jest dla Ciebie właściwą odpowiedzią. Sugeruję jednak zbudowanie systemu w taki sposób, aby można było zamienić oparty na bazie danych system kolejek na rozwiązanie pośrednie. Zgadzam się z tym artykułem. Baza danych nie jest właściwym narzędziem dla systemu opartego na kolejce, ale może być dla Ciebie wystarczająca.

System oparty na kolejkach, taki jak RabbitMq, jest zbudowany na ogromną skalę na umiarkowanym sprzęcie. Ich architektura jest w stanie to osiągnąć, unikając procesów, które spowalniają system baz danych zgodny z ACID z natury. Ponieważ magistrala komunikatów musi tylko zapewniać, że wiadomość jest przechowywana i pomyślnie przetwarzana, nie musi zawracać sobie głowy blokowaniem i zapisywaniem dzienników transakcji. Obie te koncepcje są absolutnie wymagane w przypadku systemu ACID, ale często są przyczyną sporów.

Wydajność sprowadza się do: masz tabelę SQL. Dużo odczytów i dużo zapisów. Oba wymagają pewnego rodzaju blokowania, aby zaktualizować wiersze, strony i indeksy. Twój mechanizm odpytywania stale blokuje indeks, aby wykonać na nim wyszukiwania. Zapobiega to pisaniu; w najlepszym razie są w kolejce. Kod wykonujący przetwarzanie również blokuje się, aby zaktualizować status w kolejce, gdy się zakończy lub zakończy. Tak, po optymalizacji można wykonać kwerendę, aby to działało, lub można użyć systemu zaprojektowanego specjalnie pod kątem wymaganego obciążenia pracą. RabbitMq zjada ten rodzaj pracy, nawet nie pocąc się; ponadto możesz zapisać swoją bazę danych przed obciążeniem, co daje jej więcej miejsca na skalowanie, wykonując inne czynności.

Inną rzeczą do rozważenia jest to, że większość systemów kolejek zwykle nie używa techniki odpytywania (niektóre zezwalają na HTTP, ale zaleca się unikanie używania po stronie odbierającej). RabbitMq wykorzystuje protokoły sieciowe specjalnie zaprojektowane dla magistrali komunikatów, takich jak AMPQ .

Edycja: dodawanie przypadku użycia.

Sposób, w jaki korzystałem z Rabbit, to posiadanie punktu końcowego API, który akceptuje zmianę wymagającą intensywnie używanej tabeli bazy danych. Ta tabela jest w ciągłej rywalizacji i czasami nie będzie w stanie zapisać zmiany w odpowiednim czasie z interfejsu API. Zamiast tego zapisuję żądanie zmiany w kolejce, a następnie mam usługę, która obsługuje te wiadomości, gdy tylko są w stanie. Jeśli wystąpi rywalizacja z bazą danych, kolejka po prostu rośnie, a przetwarzanie wiadomości jest opóźnione. Zwykle czas przetwarzania w dół w zakresie 14 ms, ale w czasach dużej rywalizacji dochodzimy do 2-3 sekund.

brianfeucht
źródło
Jak poradzić sobie z natychmiastową konsekwencją w tym przypadku? Jeśli publikacja zostanie wykonana, ale zaraz po niej, transakcja odpowiedzialna za aktualizację modelu domeny wycofuje się ... Oprogramowanie pośrednie byłoby całkowicie nieświadome i przetworzyłoby zdarzenie.
Mik378,
Napisałeś: „nie trzeba zawracać sobie głowy blokowaniem”. Ale z pewnością istnieje pewien rodzaj blokady, aby zapewnić rosnącą kolejność (w czasie) trasowanych zdarzeń (w kierunku pracownika), prawda?
Mik378,
@ Mik378 Spójrz na ten artykuł na temat idempotencji wiadomości . Tak, technicznie rzecz biorąc, tracisz obietnicę spójności, ale założę się, że znajdziesz to, co zyskujesz pod względem niezawodności czasu działania aplikacji i wydajności jest tego warte. Bardzo łatwo jest również zmienić sposób przetwarzania wiadomości, aby straty były dość bezbolesne.
brianfeucht
2
Tak, aby zagwarantować porządek, potrzebujesz blokady. Niektóre systemy kolejek mogą to zapewnić za cenę wydajności. Jeśli zaakceptujesz fakt, że czasami operacje będą się odbywać poza kolejnością i wymyślisz sposób radzenia sobie z tym po stronie procesora, zyskasz wykładniczo z punktu widzenia wydajności.
brianfeucht
1
@ Mik378 - Do mojej odpowiedzi dodałem przypadek użycia. Mam nadzieję, że to pomoże!
brianfeucht