Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Przewodnik po zrozumieniu wzorców skalowania bazy danych

Istnieje wiele artykułów online opisujących wzorce skalowalności bazy danych, ale są to głównie artykuły rozproszone — po prostu techniki, które są definiowane przypadkowo, bez większego kontekstu. Uważam, że nie są one definiowane krok po kroku i nie dyskutują, kiedy wybrać opcję skalowania, które opcje skalowania są wykonalne w praktyce i dlaczego.

Dlatego planuję szczegółowo omówić niektóre techniki w przyszłych artykułach. Na początek uważam, że lepiej, jeśli omówię techniki krok po kroku z pewnym kontekstem na swój własny sposób. Ten artykuł jest artykułem na wysokim poziomie — nie będę tutaj omawiał szczegółowo technik skalowania, ale przedstawię przegląd. Więc zacznijmy.

Studium przypadku

Załóżmy, że zbudowałeś startup, który oferuje współdzielenie przejazdów po niskich kosztach. Początkowo, gdy zaczynasz, kierujesz się na miasto i po pierwszej reklamie prawie nie masz dziesiątek klientów.

Zapisujesz wszystkich klientów, podróże, lokalizacje, dane rezerwacji i historię podróży klientów w tej samej bazie danych lub najprawdopodobniej na jednej fizycznej maszynie. Nie ma wymyślnego buforowania ani potoku danych big data do rozwiązywania problemów, ponieważ Twoja aplikacja jest bardzo nowa. Jest to idealne rozwiązanie dla Twojego przypadku użycia w tej chwili, ponieważ jest bardzo niewielu klientów, a Twój system prawie nie rezerwuje na przykład 1 podróży w ciągu 5 minut.

Ale z biegiem czasu coraz więcej osób zaczyna rejestrować się w Twoim systemie, ponieważ jesteś najtańszą usługą na rynku, a także dzięki promocji i reklamom. Zaczynasz rezerwować powiedzmy 10 rezerwacji na minutę i powoli liczba ta wzrasta do 20, 30 rezerwacji na minutę.

W tym momencie zdajesz sobie sprawę, że system zaczął działać słabo:opóźnienie API znacznie wzrosło, a niektóre transakcje zakleszczają się lub zanikają, a ostatecznie kończą się niepowodzeniem. Twoja aplikacja potrzebuje więcej czasu na odpowiedź, powodując niezadowolenie klientów. Co możesz zrobić, aby rozwiązać problem?

Wzorzec 1 — optymalizacja zapytań i implementacja puli połączeń:

Pierwszym rozwiązaniem, które przychodzi na myśl, jest to, że pamięć podręczna często wykorzystuje dane niedynamiczne, takie jak historia rezerwacji, historia płatności, profile użytkowników i tak dalej. Ale po tym buforowaniu warstwy aplikacji nie można rozwiązać problemu opóźnień interfejsów API, które ujawniają dynamiczne dane, takie jak aktualna lokalizacja kierowcy lub najbliższe taksówki dla danego klienta lub aktualny koszt podróży w określonym momencie po rozpoczęciu podróży.

Stwierdzasz, że Twoja baza danych jest prawdopodobnie mocno znormalizowana, więc wprowadzasz nadmiarowe kolumny (te kolumny często pojawiają się w WHERE lub JOIN ON w zapytaniach) w często używanych tabelach ze względu na denormalizację. Zmniejsza to liczbę zapytań łączących, dzieli duże zapytanie na wiele mniejszych zapytań i dodaje ich wyniki w warstwie aplikacji.

Inną równoległą optymalizacją, którą możesz zrobić, jest poprawianie połączeń z bazą danych. Biblioteki klienta bazy danych i biblioteki zewnętrzne są dostępne w prawie wszystkich językach programowania. Możesz użyć bibliotek puli połączeń do buforowania połączeń z bazą danych lub możesz skonfigurować rozmiar puli połączeń w samym systemie zarządzania bazą danych.

Tworzenie dowolnego połączenia sieciowego jest kosztowne, ponieważ wymaga komunikacji w obie strony między klientem a serwerem. Pula połączeń może pomóc zoptymalizować liczbę połączeń. Biblioteki puli połączeń mogą pomóc w tworzeniu połączeń multipleksowych — wiele wątków aplikacji może korzystać z tego samego połączenia z bazą danych. Zobaczę, czy będę mógł szczegółowo wyjaśnić łączenie połączeń w osobnym artykule później.

Zmierz opóźnienie swoich interfejsów API i znajdź prawdopodobnie 20–50% lub więcej skróconego opóźnienia. W tej chwili jest to dobra optymalizacja.

Teraz przeskalowałeś swój biznes do jeszcze jednego miasta, rejestruje się więcej klientów, powoli zaczynasz robić 80-100 rezerwacji na minutę. Twój system nie jest w stanie obsłużyć tej wagi. Ponownie widzisz wzrost opóźnień API, warstwa bazy danych zrezygnowała, ale tym razem żadna optymalizacja zapytań nie zapewnia znaczącego wzrostu wydajności. Sprawdzasz metrykę systemu, stwierdzasz, że miejsce na dysku jest prawie pełne, procesor jest zajęty przez 80% czasu, pamięć RAM zapełnia się bardzo szybko.

Wzorzec 2 — Skalowanie w pionie lub Skalowanie w górę:

Po zbadaniu wszystkich wskaźników systemowych wiesz, że nie ma innego prostego rozwiązania niż modernizacja sprzętu systemu. Zwiększasz rozmiar pamięci RAM 2 razy, zwiększasz miejsce na dysku, powiedzmy, 3 razy lub więcej. Nazywa się to skalowaniem pionowym lub skalowaniem systemu. Informujesz swój zespół ds. infrastruktury, zespół Devops lub agentów centrum danych innych firm, aby zaktualizować swoją maszynę.

Ale jak skonfigurować maszynę do skalowania pionowego?

Przydzielasz większą maszynę. Jednym ze sposobów nie jest ręczna migracja danych ze starego komputera, ale ustawienie nowego komputera jako replica do istniejącego komputera (primary )-utwórz tymczasową primary replica konfiguracja. Pozwól, aby replikacja zaszła naturalnie. Po zakończeniu replikacji awansuj nową maszynę na podstawową i przełącz starszą maszynę w tryb offline. Ponieważ oczekuje się, że większa maszyna będzie obsługiwać wszystkie żądania, wszystkie operacje odczytu/zapisu będą miały miejsce na tej maszynie.

Fajny. Twój system znów działa i działa ze zwiększoną wydajnością.

Twoja firma ma się bardzo dobrze i decydujesz się na skalowanie do 3 dodatkowych miast — teraz działasz w sumie w 5 miastach. Ruch jest 3 razy większy niż wcześniej, oczekuje się, że zrobisz około 300 rezerwacji na minutę. Zanim jeszcze osiągniesz tę rezerwację celu, ponownie napotkasz kryzys wydajności, rozmiar indeksu bazy danych znacznie wzrasta w pamięci, wymaga ciągłej konserwacji, skanowanie tabel za pomocą indeksu staje się wolniejsze niż kiedykolwiek. Kalkulujesz koszt dalszego przeskalowania maszyny, ale nie jesteś przekonany o kosztach. Co teraz robisz?

Wzorzec 3 — Segregacja odpowiedzialności za zapytanie (CQRS):

Stwierdzasz, że duża maszyna nie jest w stanie obsłużyć wszystkich read/write upraszanie. Również w większości przypadków każda firma potrzebuje możliwości transakcyjnych na write ale nie przy read operacje. Nie przeszkadza ci też trochę niespójnego lub opóźnionego read operacje i Twoja firma również nie ma z tym problemu. Widzisz okazję, w której dobrym rozwiązaniem może być oddzielenie read &write operacje fizyczne mądre. Stworzy to zakres dla poszczególnych maszyn, aby obsłużyć więcej read/write operacje.

Teraz bierzesz jeszcze dwie duże maszyny i konfigurujesz je jako replica do bieżącej maszyny. Replikacja bazy danych zajmie się dystrybucją danych z primary maszyna do replica maszyny. Nawigujesz po wszystkich zapytaniach odczytu (Query (Q ) w CQRS ) do replik — dowolna replica może obsłużyć dowolne żądanie odczytu, nawigujesz po wszystkich zapytaniach zapisu (Command (C ) w CQRS ) do primary . Może wystąpić niewielkie opóźnienie w replikacji, ale w zależności od przypadku użycia w Twojej firmie, jest to w porządku.

Większość startupów średniej skali, które codziennie obsługują kilkaset tysięcy żądań, może przetrwać z konfiguracją podstawowej repliki, pod warunkiem, że okresowo archiwizują starsze dane.

Teraz skalujesz do 2 kolejnych miast, widzisz, że Twój primary nie jest w stanie obsłużyć wszystkich write upraszanie. Wiele write żądania mają opóźnienie. Co więcej, opóźnienie między primary &replica czasami wpływa na klientów i kierowców np. — po zakończeniu podróży klient płaci kierowcy z powodzeniem, ale kierowca nie może zobaczyć płatności, ponieważ aktywność klienta to write żądanie, które trafia do primary , podczas gdy czynność kierowcy to read żądanie, które trafia do jednej z replik. Twój system jest tak powolny, że kierowca nie widzi płatności przez co najmniej pół minuty, co jest frustrujące zarówno dla kierowcy, jak i klienta. Jak to rozwiązać?

Wzorzec 4 — Wielokrotna replikacja podstawowa

Skalowałeś się naprawdę dobrze z primary-replica konfiguracji, ale teraz potrzebujesz większej wydajności zapisu. Możesz być gotowy na małe kompromisy przy read zażądać wydajności. Dlaczego nie rozesłać żądania zapisu do replica również?

W multi-primary konfiguracja, wszystkie maszyny mogą pracować jako primary &replica . Możesz pomyśleć o multi-primary jako krąg maszyn powiedz A->B->C->D->A . B może replikować dane z A , C może replikować dane z B , D może replikować dane z C , A może replikować dane z D . Możesz zapisać dane do dowolnego węzła, podczas odczytu danych możesz rozesłać zapytanie do wszystkich węzłów, ktokolwiek odpowie, zwróci je. Wszystkie węzły będą miały ten sam schemat bazy danych, ten sam zestaw tabel, indeks itp. Musisz więc upewnić się, że nie ma kolizji w id między węzłami w tej samej tabeli, w przeciwnym razie podczas rozgłaszania wiele węzłów zwróciłoby różne dane dla tego samego id .

Generalnie lepiej jest użyć UUID lub GUID dla id. Jeszcze jedną wadą tej techniki jest — read zapytania mogą być nieefektywne, ponieważ wiążą się z rozgłaszaniem zapytania i uzyskaniem prawidłowego wyniku — w zasadzie metodą zbierania rozproszonego.

Teraz skalujesz do 5 kolejnych miast, a Twój system znowu boli. Oczekuje się, że obsłużysz około 50 żądań na sekundę. Jesteś w rozpaczliwej potrzebie obsługi dużej liczby jednoczesnych żądań. Jak to osiągnąć?

Wzorzec 5 — Partycjonowanie:

Wiesz, że Twoja location baza danych jest czymś, co robi wysokie write &read ruch drogowy. Prawdopodobnie write:read stosunek to 7:3 . Wywiera to dużą presję na istniejące bazy danych. location tabele zawierają kilka podstawowych danych, takich jak longitude , latitude , timestamp , driver id , trip id itp. Nie ma to wiele wspólnego z podróżami użytkowników, danymi użytkownika, danymi płatności itp. A co z oddzieleniem location tabele w osobnym schemacie bazy danych? Co powiesz na umieszczenie tej bazy danych na oddzielnych komputerach z odpowiednią primary-replica? lub multi-primary konfiguracja?

Nazywa się to partycjonowaniem danych według funkcjonalności. Różne bazy danych mogą zawierać dane podzielone na kategorie według różnych funkcji, w razie potrzeby wynik można zagregować w warstwie zaplecza. Korzystając z tej techniki, możesz skupić się na dobrym skalowaniu tych funkcji, które wymagają wysokiego read/write upraszanie. Chociaż zaplecze lub warstwa aplikacji musi wziąć odpowiedzialność za dołączenie do wyników w razie potrzeby, co prawdopodobnie spowoduje więcej zmian w kodzie.

Teraz wyobraź sobie, że rozszerzyłeś swoją działalność na łącznie 20 miast w swoim kraju i planujesz wkrótce rozszerzyć działalność na Australię. Twoje rosnące zapotrzebowanie na aplikację wymaga szybszej i szybszej reakcji. Żadna z powyższych metod nie może teraz pomóc ci w skrajności. Musisz skalować swój system w taki sposób, aby ekspansja na inne kraje/regiony nie zawsze wymagała częstych zmian inżynieryjnych lub architektonicznych. Jak to robisz?

Wzorzec 6 — Skalowanie w poziomie:

Dużo googlujesz, dużo czytasz o tym, jak inne firmy rozwiązały ten problem — i dochodzisz do wniosku, że musisz skalować poziomo. Przydzielasz powiedzmy 50 maszyn — wszystkie mają ten sam schemat bazy danych, który z kolei zawiera ten sam zestaw tabel. Wszystkie maszyny przechowują tylko część danych.

Ponieważ wszystkie bazy danych zawierają ten sam zestaw tabel, można zaprojektować system w taki sposób, aby istniała lokalność danych, tj.; wszystkie powiązane dane trafiają do tej samej maszyny. Każda maszyna może mieć własne repliki, repliki mogą służyć do odzyskiwania po awarii. Każda z baz danych nazywa się shard . Fizyczna maszyna może mieć jeden lub wiele shards — to zależy od twojego projektu, jak chcesz. Musisz zdecydować się na sharding key w taki sposób, że pojedynczy sharding key zawsze odnosi się do tej samej maszyny. Więc możesz sobie wyobrazić wiele maszyn, które przechowują powiązane dane w tym samym zestawie tabel, read/write żąda tego samego wiersza lub tego samego zestawu zasobów na tej samej maszynie bazy danych.

Sharding jest generalnie trudny — przynajmniej tak mówią inżynierowie z różnych firm. Ale kiedy obsługujesz miliony lub miliardy żądań, musisz podjąć tak trudną decyzję.

Omówię sharding bardziej szczegółowo w następnym poście, więc powstrzymuję się od dalszej dyskusji w tym poście.

Teraz, gdy masz już sharding, masz pewność, że możesz skalować do wielu krajów. Twój biznes urósł tak bardzo, że inwestorzy naciskają na skalowanie biznesu na różnych kontynentach. Znowu widzisz tu jakiś problem. Znowu opóźnienie API. Twoja usługa jest hostowana w USA, a ludzie z Wietnamu mają trudne przejażdżki z rezerwacją czasu. Czemu? Co z tym zrobisz?

Wzorzec 7 — partycja Data Center Wise:

Twoja firma rozwija się w Ameryce, Azji Południowej i kilku krajach Europy. Codziennie dokonujesz milionów rezerwacji, a na Twój serwer trafiają miliardy żądań. Gratulacje - to szczytowy moment dla Twojej firmy.

Ale ponieważ żądania z aplikacji muszą podróżować przez kontynenty przez setki lub tysiące serwerów w Internecie, pojawia się opóźnienie. A co z dystrybucją ruchu w centrach danych? Możesz założyć centrum danych w Singapurze, które obsługuje wszystkie żądania z Azji Południowej, centrum danych w Niemczech może obsługiwać wszystkie żądania z krajów europejskich, a centrum danych w Kalifornii może obsługiwać wszystkie żądania z USA.

Włączasz również replikację między centrami danych, która pomaga w odzyskiwaniu danych po awarii. Jeśli więc centrum danych w Kalifornii wykona replikację do centrum danych w Singapurze, w przypadku awarii centrum danych w Kalifornii z powodu problemu z elektrycznością lub klęski żywiołowej, wszystkie żądania USA mogą wrócić do centrum danych w Singapurze i tak dalej.

Ta technika skalowania jest przydatna, gdy masz miliony klientów do obsługi w różnych krajach i nie możesz pogodzić się z utratą danych, musisz zawsze utrzymywać dostępność systemu.

Oto kilka ogólnych technik skalowania bazy danych krok po kroku. Chociaż większość inżynierów nie ma wystarczającej szansy na wdrożenie tych technik, ale ogólnie lepiej jest uzyskać szersze pojęcie o takim systemie, które w przyszłości może pomóc w lepszym projektowaniu systemu i architektury.

W kolejnych artykułach postaram się szczegółowo omówić niektóre koncepcje. Zachęcamy do wyrażenia odpowiedniej opinii na temat tego posta, jeśli taka istnieje.

Artykuł został pierwotnie opublikowany na koncie medium autora:https://medium.com/@kousiknath/understanding-database-scaling-patterns-ac24e5223522



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak utworzyć złożony klucz podstawowy w MySQL

  2. mysql:uzyskaj liczbę rekordów między dwiema datami i godzinami

  3. Czy Python obsługuje przygotowane instrukcje MySQL?

  4. używanie wartości null w przygotowanym oświadczeniu mysqli

  5. Odmowa dostępu dla użytkownika 'root'@'localhost' z PHPMyAdmin