Nie ma jednoznacznego rozwiązania, ponieważ zależy to całkowicie od kontekstu - w szczególności, od których wymiarów system ma się skalować i jakie są twoje rzeczywiste problemy. Czy baza danych jest naprawdę twoim wąskim gardłem?
Ta (niestety dość długa) odpowiedź brzmi trochę jak „mikrousług są złe, monolity na całe życie!”, Ale to nie jest moja intencja. Chodzi mi o to, że mikrousługi i rozproszone bazy danych mogą rozwiązać różne problemy, ale nie bez własnych problemów. Aby uzasadnić swoją architekturę, musisz pokazać, że te problemy nie mają zastosowania, można je złagodzić i że architektura ta jest najlepszym wyborem dla potrzeb Twojej firmy.
Rozproszone dane są trudne.
Ta sama elastyczność, która umożliwia lepsze skalowanie, to druga strona słabszych gwarancji. Warto zauważyć, że systemy rozproszone są znacznie trudniejsze do uzasadnienia.
Aktualizacje atomowe, transakcje, spójność / integralność referencyjna i trwałość są niezwykle cenne i nie należy z nich rezygnować pochopnie. Nie ma sensu mieć danych, jeśli są niekompletne, nieaktualne lub całkowicie błędne. Jeśli masz ACID jako wymaganie biznesowe, ale korzystasz z technologii baz danych, która nie jest w stanie zaoferować go od razu (np. Wiele baz danych NoSQL lub architektura DB-per-microservice), Twoja aplikacja musi wypełnić lukę i zapewnić te gwarancje.
Nie jest to niemożliwe, ale trudne do zrobienia. Bardzo trudne. Zwłaszcza w ustawieniu rozproszonym, w którym do każdej bazy danych jest wielu autorów. Ta trudność przekłada się na dużą szansę na błędy, w tym prawdopodobnie upuszczone dane, niespójne dane i tak dalej.
Rozważ na przykład przeczytanie analiz Jepsen dobrze znanych rozproszonych systemów baz danych , być może zaczynając od analizy Cassandry . Nie rozumiem połowy tej analizy, ale TL; DR jest taki, że systemy rozproszone są tak trudne, że nawet wiodące w branży projekty czasami mylą się, w sposób, który może wydawać się oczywisty z perspektywy czasu.
Systemy rozproszone wymagają również większego wysiłku rozwojowego. Do pewnego stopnia istnieje bezpośredni kompromis między kosztami programowania lub spadaniem pieniędzy na mocniejszy sprzęt.
Przykład: wiszące odniesienia
W praktyce nie powinieneś patrzeć na informatykę, ale na wymagania biznesowe, aby sprawdzić, czy i jak można rozluźnić ACID. Np. Wiele relacji z kluczem obcym może nie być tak ważne, jak się wydaje. Rozważ związek produkt - kategoria n: m. W RDBMS możemy zastosować ograniczenie klucza obcego, aby tylko istniejące produkty i istniejące kategorie mogły być częścią tego związku. Co się stanie, jeśli wprowadzimy oddzielne usługi dotyczące produktów i kategorii, a produkt lub kategoria zostaną usunięte?
W takim przypadku może to nie stanowić większego problemu i możemy napisać naszą aplikację, aby odfiltrowała wszelkie produkty lub kategorie, które już nie istnieją. Ale są kompromisy!
Należy pamiętać, że może to wymagać poziomu aplikacji JOIN
w wielu bazach danych / mikrousługach, co jedynie przenosi przetwarzanie z serwera bazy danych do aplikacji. Zwiększa to całkowite obciążenie i musi przenosić dodatkowe dane przez sieć.
Może to zepsuć podział na strony. Np. Zamawiasz kolejne 25 produktów z kategorii i odfiltrowujesz niedostępne produkty z tej odpowiedzi. Teraz Twoja aplikacja wyświetla 23 produkty. Teoretycznie możliwa byłaby również strona z zerowymi produktami!
Od czasu do czasu będziesz chciał uruchomić skrypt, który czyści zwisające odwołania, po każdej odpowiedniej zmianie lub w regularnych odstępach czasu. Zauważ, że takie skrypty są dość drogie, ponieważ muszą żądać każdego produktu / kategorii z bazy danych / mikrousługi, aby sprawdzić, czy nadal istnieje.
Powinno to być oczywiste, ale dla jasności: nie używaj ponownie identyfikatorów. Identyfikatory w stylu autoinkrementacji mogą, ale nie muszą być w porządku. Identyfikatory GUID lub skróty zapewniają większą elastyczność, np. Dzięki możliwości przypisania identyfikatora przed wstawieniem elementu do bazy danych.
Przykład: współbieżne zamówienia
Zamiast tego rozważ stosunek produktu do zamówienia. Co stanie się z zamówieniem, jeśli produkt zostanie usunięty lub zmieniony? Ok, możemy po prostu skopiować odpowiednie dane produktu do pozycji zamówienia, aby były dostępne - aby uprościć wymianę miejsca na dysku. Ale co jeśli cena produktu ulegnie zmianie lub produkt stanie się niedostępny tuż przed złożeniem zamówienia na ten produkt? W systemie rozproszonym rozprzestrzenianie się efektów zajmuje trochę czasu, a kolejność prawdopodobnie przejdzie przez nieaktualne dane.
Ponownie, jak podejść do tego, zależy od wymagań biznesowych. Być może nieaktualne zamówienie jest akceptowalne i możesz później anulować zamówienie, jeśli nie może zostać zrealizowane.
Ale może nie jest to opcja, np. W przypadku wysoce współbieżnych ustawień. Weź pod uwagę 3000 osób, które spieszą się, aby kupić bilety na koncert w ciągu pierwszych 10 sekund, i załóżmy, że zmiana dostępności będzie wymagała 10 ms do rozpowszechnienia. Jakie jest prawdopodobieństwo sprzedania ostatniego biletu wielu osobom? Zależy jak te kolizje są obsługiwane, ale stosując rozkład Poissona z λ = 3000 / (10s / 10ms) = 3
otrzymujemy P(k > 1) = 1 - P(k = 0) - P(k = 1) = 80%
szansę zderzenia na 10ms interwał. To, czy sprzedaż, a później anulowanie większości zamówień jest możliwe bez popełniania oszustwa, może prowadzić do interesującej rozmowy z działem prawnym.
Pragmatyzm oznacza wybieranie najlepszych funkcji.
Dobrą wiadomością jest to, że nie musisz przechodzić na model rozproszonej bazy danych, jeśli nie jest to wymagane w inny sposób. Nikt nie cofnie członkostwa w Microservice Club, jeśli nie wykonasz mikrousług „odpowiednio”, ponieważ nie ma takiego klubu - i nie ma jednego prawdziwego sposobu na zbudowanie mikrousług.
Pragmatyzm wygrywa za każdym razem, więc mieszaj i dopasowuj różne podejścia, gdy rozwiążą twój problem. Może to nawet oznaczać mikrousługi ze scentralizowaną bazą danych. Naprawdę, nie przechodź przez ból rozproszonych baz danych, jeśli nie musisz.
Możesz skalować bez mikrousług.
Mikrousługi mają dwie główne zalety:
- Korzyści organizacyjne związane z tym, że można je opracowywać i wdrażać niezależnie przez oddzielne zespoły (co z kolei wymaga, aby usługi oferowały stabilny interfejs).
- Korzyści operacyjne wynikające z tego, że każdą mikrousługę można skalować niezależnie .
Jeśli niezależne skalowanie nie jest wymagane, mikrousługi są znacznie mniej atrakcyjne.
Serwer bazy danych jest już rodzajem usługi, którą można skalować (nieco) niezależnie, np. Dodając repliki odczytu. Wspominasz o procedurach przechowywanych. Zmniejszenie ich może mieć tak duży efekt, że wszelkie inne dyskusje na temat skalowalności są dyskusyjne.
I jest całkowicie możliwe posiadanie skalowalnego monolitu, który obejmuje wszystkie usługi jako biblioteki. Następnie można skalować, uruchamiając więcej instancji monolitu, co oczywiście wymaga, aby każda instancja była bezstanowa.
Zwykle działa to dobrze, dopóki monolit nie będzie zbyt duży, aby można go było rozsądnie wdrożyć, lub jeśli niektóre usługi mają specjalne wymagania dotyczące zasobów, aby można było skalować je niezależnie. Domeny problemowe wymagające dodatkowych zasobów mogą nie obejmować osobnego modelu danych.
Czy masz mocne uzasadnienie biznesowe?
Zdajesz sobie sprawę z potrzeb biznesowych Twojej organizacji i dlatego możesz stworzyć argument oparty na architekturze bazy danych dla mikrousług na podstawie analizy:
- że wymagana jest pewna skala, a ta architektura jest najbardziej opłacalnym podejściem do uzyskania tej skalowalności, biorąc pod uwagę wzmożony wysiłek na rzecz opracowania takiej konfiguracji i alternatywnych rozwiązań; i
- że wymagania biznesowe pozwalają na złagodzenie odpowiednich gwarancji ACID, bez powodowania różnych problemów, takich jak te omówione powyżej.
I odwrotnie, jeśli nie jesteś w stanie tego wykazać, w szczególności jeśli obecny projekt bazy danych jest w stanie obsłużyć wystarczającą skalę w przyszłości (jak sądzą koledzy), to również masz odpowiedź.
Istnieje również duży składnik YAGNI do skalowalności. W obliczu niepewności jest to strategiczna decyzja biznesowa dotycząca budowania skalowalności (niższe całkowite koszty, ale wiążą się z kosztami alternatywnymi i mogą nie być potrzebne) w porównaniu z odroczeniem prac nad skalowalnością (w razie potrzeby wyższe całkowite koszty, ale masz lepsze idea rzeczywistej skali). Nie jest to przede wszystkim decyzja techniczna.