Interakcja z danymi przy użyciu wielu baz danych / serwerów

18

Wszystkie projekty, z którymi do tej pory miałem do czynienia, wymagały tylko jednej bazy danych na jednym serwerze. Chciałbym dowiedzieć się więcej o tym, w jaki sposób projekty wymagające skalowania przechodzą do wielu baz danych i / lub serwerów, aby pomóc w zarządzaniu obciążeniem. Mam świadomość wysokiej skalowalności , ale szczególnie interesują mnie przykłady kodu lub dodatkowe zasoby, w których mogłem przeczytać więcej na ten temat.

Na przykład:

  • Jak budowane są sprzężenia między dwiema tabelami w wielu bazach danych? (Przydałby się tutaj przykładowy kod).
  • Czy są jakieś specjalne strategie śledzenia, które tabele znajdują się w której bazie danych?
  • Czy kod aplikacji musi wiedzieć, że jedna lub więcej baz danych jest rozproszonych na wielu serwerach? Jeśli nie, na jakim poziomie żądania są filtrowane?
  • Kiedy należy wyjść poza konfigurację 1 bazy danych / 1 serwera? Jak często trzeba to robić?
VirtuosiMedia
źródło
Na to pytanie można lepiej odpowiedzieć administratorom baz danych . Jednak nie ma w tym nic złego, więc po prostu sprawdzę mody DBA. Jeśli jest to odpowiednie, czy chcesz migrować?
Adam Lear
@AnnaLear - Myślę, że to zależy od odpowiedzi. W tym momencie bardziej interesuje mnie kwestia aplikacji, więc na razie myślę, że może być lepiej tutaj.
VirtuosiMedia,
@AnnaLear ack, zgódź się z OP, a następnie, jeśli chcą kodu specyficznego dla aplikacji.
jcolebrand

Odpowiedzi:

13

Ok, podzielmy to:

  • Jak budowane są sprzężenia między dwiema tabelami w wielu bazach danych? (Przydałby się tutaj przykładowy kod).

To całkiem proste. Obiekty SQL mają dowolną konwencję nazewnictwa od jednej do czterech części:

Servername.databasename.schemaname.tablename

Jeśli wszystkie tabele znajdują się na tym samym serwerze w tej samej bazie danych, z tym samym właścicielem / schematem, możesz po prostu zignorować pierwsze trzy części i użyć tego, do czego najczęściej jesteś przyzwyczajony:

Select a.*,b.* from 
tableA a inner join 
tableB b on a.col1=b.col1

Jeśli jedna z tabel znajduje się w innej bazie danych i obie używają domyślnego schematu dla swoich baz danych, po prostu dodajesz bazę danych do drugiej tabeli:

Select a.*,b.* from 
tableA a inner join 
databaseC..tableB b on a.col1 = b.col1

Jeśli akurat znajdujesz się w trzeciej bazie danych innej niż ta, której dotyczy zapytanie, jawnie użyj obu nazw baz danych:

Select a.*,b.* from 
databaseD..tableA a inner join 
databaseC..tableB b on a.col1 = b.col1

Jeśli w końcu użyjesz różnych schematów i / lub właścicieli, możesz dodać je w:

Select a.*,b.* from 
databaseD.john.tableA a inner join 
databaseC.accounting.tableB b on a.col1 = b.col1

I na koniec, jeśli jesteś bardzo ostrożny i masz bardzo dobry powód, możesz dołączyć do (zwykle małej) tabeli na innym serwerze:

Select a.* from 
databaseD.john.TableA a inner join 
ATLANTA.databaseC.accounting.tableB b on a.col1 = b.col1
  • Kiedy należy wyjść poza konfigurację 1 bazy danych / 1 serwera? Jak często trzeba to robić? Czy są jakieś specjalne strategie śledzenia, które tabele znajdują się w której bazie danych?

Połączę te dwa, ponieważ idą w parze. Prawie zawsze dobrze jest zacząć od założenia, że ​​jedna baza danych wystarcza na jeden serwer, dopóki ograniczenia projektowe / biznesowe / techniczne nie zmuszą Cię do korzystania z większej ilości.

Aby więc najpierw odpowiedzieć na drugie pytanie, ponieważ generalnie masz powód posiadania oddzielnych baz danych, powinno to być dość oczywiste ze znajomości projektu systemu, w którym coś jest.

Co do tego, kiedy / dlaczego konieczne jest przejście poza jedną bazę danych. Zwykle jest to mieszanka reguł biznesowych, polityki i / lub powodów technicznych.

Na przykład tam, gdzie pracuję, mamy 16 baz danych rozproszonych na 4 serwerach. Mamy MainDB, ImageDB, referencetableDB, HighvolumeTransactionDB, ReportingDB, StagingDB, ProcessingDB, ArchiveDB, FinancialDB. Aby podać przykłady, dlaczego się różnią:

  • FinancialDB, informacje wrażliwe
  • Baza danych obrazów, określone różne wymagania dotyczące przechowywania i odzyskiwania
  • ReferenceDB, niska transakcja, wysoki odczyt
  • ReportingDB, bardzo wysoki odczyt, musi zostać przywrócony / zreplikowany w różnych innych środowiskach, w przeciwieństwie do wielu innych danych
  • StagingDB, nic stałego, tylko rozbudowana tempdb, nad którą mamy większą kontrolę
  • MainDB, interfejsy z wszystkimi innymi bazami danych, ale wymaga różnicowych kopii zapasowych, więc ... rozdzieliliśmy
  • Tabele HighVolumeTransaction (które są stosunkowo przejściowe) do ich własnej bazy danych, aby zachować rozsądny rozmiar kopii zapasowej.
  • Archiwum, wiele takich samych danych z Main i Reporting, ale z dłuższymi okresami przechowywania i trudniejszymi zapytaniami sięgającymi głęboko w dane. Gdyby to było nadal połączone z Main / Reporting, spowodowałoby to zapadnięcie się naszego systemu.

Czy kod aplikacji musi wiedzieć, że jedna lub więcej baz danych jest rozproszonych na wielu serwerach? Jeśli nie, na jakim poziomie żądania są filtrowane?

W szerokim sensie prawdopodobnie tak. Muszą przynajmniej wiedzieć, na jaki serwer wskazują w ciągu połączenia z bazą danych. Przetwarzanie, raportowanie, główne itp.

Stamtąd potrzebują kontekstu bazy danych, aby wykonać. Zasadniczo byłby to najczęściej używany w aplikacji, być może nawet oryginalny z jednej bazy danych / jednego serwera dni aplikacji. MOŻESZ mieć aplikację wyraźnie przełączającą kontekst bazy danych przy każdym wywołaniu, ale bardzo utrudnia to dostosowanie bazy danych bez zmiany aplikacji.

Zwykle (a przynajmniej MY zwykle) podejście polega na tym, aby zawsze uzyskiwać dostęp za pośrednictwem jednej lub dwóch głównych baz danych.

Następnie w razie potrzeby utwórz widoki do innych baz danych w połączeniu z łączeniem się z bazą danych za pomocą procedur przechowywanych.

Aby zilustrować:

Załóżmy, że chcesz uzyskać informacje demograficzne klienta, dane sprzedaży i saldo kredytu, które są rozłożone na trzy tabele pierwotnie wszystkie w MainDB.

Więc piszesz połączenie ze swojej aplikacji:

Select c.ClientName, c.ClientAddress, s.totalSales,f.CreditBlance from
Clients c join Sales s on c.clientid = s.clientid inner join AccountReceivable f on 
c.clientid=f.clientid where c.clientid = @clientid

Niesamowite. Jednak teraz za każdym razem, gdy zmieniamy nazwę kolumny lub zmieniamy nazwę / przenosimy tabelę, musisz zaktualizować kod aplikacji. Zamiast tego robimy dwie rzeczy:
Tworzymy klientów, Sprzedaż, Widoki Konta Odbiorcy (nie używałbyś Select *, ale tutaj demonstruję)

Use MainDB
GO
Create view v_Clients as select * from Clients
Create view v_Sales as select * from Sales
Create view v_AccountReceivable as select * from AccountReceivable
Go

Następnie utworzylibyśmy również procedurę przechowywaną, spGetClientSalesAR

Create proc spGetClientSalesAR @clientID int
as
Select c.ClientName as ClientName, 
       c.ClientAddress as ClientAddress, 
       s.totalSales as TotalSales, 
       f.CreditBlance as CreditBalance 
from
v_Clients c join v_Sales s 
    on c.clientid = s.clientid 
inner join v_AccountReceivable f 
    on c.clientid=f.clientid 
where c.clientid = @clientid

I niech twoja aplikacja to nazwie.

Teraz, dopóki nie zmieniam interfejsu w tym przechowywanym proc, mogę praktycznie zrobić wszystko, co muszę zrobić z bazą danych zaplecza, aby zwiększyć lub zmniejszyć.

W skrajności mógłbym nawet uczynić mój stary MainDB tylko zbiorem procedur przechowywanych w skorupie i widokami, tak że pod tymi widokami, które stworzyliśmy, wyglądało to tak:

Create view v_Clients as select * from ServerX.DatabaseY.dbo.Clients
Create view v_Sales as select * from ServerQ.DatabaseP.dbo.Sales
Create view v_AccountReceivable as select * from ServerJ.DatabaseK.dbo.AccountReceivable

A Twoja aplikacja nigdy nie pozna różnicy (zakładając między innymi szybkie rury i dobrze zainscenizowane dane).

Oczywiście to ekstremalne i kłamałbym, gdybym powiedział, że wszystko zostało zaplanowane w ten sposób, ale korzystanie z procedur / widoków przechowywanych, nawet jeśli robisz to podczas refaktoryzacji, zapewni ci dużą elastyczność, gdy Twoja aplikacja wyrasta ze skromnej bazy danych / jednego serwera początek.

TetonSig
źródło
TetonSig - Dzięki za odpowiedź. Nie byłem w stanie wrócić do pytania na czas, aby przyznać ci pełną nagrodę (podróżowałem), ale utworzyłem nową nagrodę za pytanie i będę mógł ci ją przyznać w ciągu 24 godzin.
VirtuosiMedia,
Wow, dzięki. Doceniam to. Odpowiadanie na pytanie było bardzo zabawne.
TetonSig
5

Podstawowym sposobem, w jaki spotkałem wiele serwerów baz danych w świecie internetowym (ponieważ pytanie jest oznaczone jako PHP), są konfiguracje, w których istniała jedna baza „master” (zapis), a następnie jedna lub więcej replikowanych „slave” (read) baz danych . Zapisy w bazie danych są wykonywane na bazie danych „master”. Zawartość tej bazy danych jest replikowana na serwery „slave” w czasie prawie rzeczywistym. Zapytania - szczególnie intensywne raporty - są następnie uruchamiane względem jednej z baz danych „slave”, aby przenieść obciążenie na te serwery. Należy pamiętać, że ta konkretna konfiguracja jest najlepsza dla aplikacji, które mają dużo odczytów, ale nie dużo pisania. W żadnym wypadku nie jest to jedyny sposób na uporządkowanie rzeczy.

Grandmaster B.
źródło
3

Jak budowane są sprzężenia między dwiema tabelami w wielu bazach danych? (Przydałby się tutaj przykładowy kod).

Oni nie są. Bazy danych NoSQL w ogóle nie wykonują sprzężeń, a nawet gdybyś mógł wykonać sprzężenie SQL między serwerami RDBMS, nie chciałbyś, jeśli cenisz wydajność (por. Błędy przetwarzania rozproszonego ).

Czy są jakieś specjalne strategie śledzenia, które tabele znajdują się w której bazie danych?

W relacyjnej bazie danych SQL partycjonowanie zwykle odbywa się w ramach jednego serwera / bazy danych, przy użyciu różnych plików umieszczonych na różnych dyskach. Niemal z definicji rozwiązanie do skalowania w poziomie oznacza, że wszystkie bazy danych mają wszystkie tabele, a także masz jakieś transakcyjne tworzenie kopii lustrzanych, replikacja lub niestandardowe rozwiązanie zapewniające spójność ostateczną, aby mieć pewność, że wszystkie dane dotrą tam, gdzie powinny.

Jeśli faktycznie dzielisz bazę danych logicznie, a nie tylko fizycznie, to mapowania zdefiniowane w DAL lub ORM zadeklarują, które tabele znajdują się w której bazie danych.

Bazy danych NoSQL to połączenie rozwiązań partycjonujących. Czasami partycjonowane są „tabele” (lub częściej „kolekcje”). Innym razem są to „wiersze” (lub „dokumenty”). W niektórych przypadkach tak naprawdę są to kolumny , jak w zorientowanej na kolumny bazie danych, takiej jak HBase. Zależy to całkowicie od używanej technologii. Jedną z nich wszystkich jest to, że sam silnik śledzi to wszystko, więc wszystko, co musisz zrobić, to poprosić o dokument lub wiersz.

To oczywiście zakładając, że faktycznie korzystasz z funkcji dzielenia fragmentów, a nie tylko tworzysz kilka różnych baz danych. Jeśli robisz to drugie, to jesteś sam.

Czy kod aplikacji musi wiedzieć, że jedna lub więcej baz danych jest rozproszonych na wielu serwerach? Jeśli nie, na jakim poziomie żądania są filtrowane?

Jeśli są to różne logiczne bazy danych, tak. Jeśli są one rozproszone tylko fizycznie, to nie - przy założeniu, że twoja konkretna baza danych natywnie obsługuje dzielenie na fragmenty lub używasz rozwiązania równoważenia obciążenia (dla baz danych SQL). Zakładając również, że wszystkie twoje operacje są bezpaństwowe; jeśli chcesz skalowania w poziomie, będziesz musiał zrezygnować z ACID.

Kiedy należy wyjść poza konfigurację 1 bazy danych / 1 serwera? Jak często trzeba to robić?

Nadszedł czas, aby zoptymalizować wszystko, co możliwe na jednym serwerze, i nadal nie jest w stanie wycisnąć wystarczającej wydajności z powodu ograniczeń obciążenia we / wy. Jeśli musisz zadać pytanie, jest za wcześnie.

Zauważ, że problemy z wydajnością w przyzwoitym produkcie RDBMS (Oracle, SQL Server) są częściej spowodowane złym projektem, słabym indeksowaniem, słabymi zapytaniami, rywalizacją o blokadę i tak dalej; produkty te można skalować w pionie w absurdalnym stopniu. Powtórz więc, powinieneś rozważyć „wyjście poza konfigurację 1 bazy danych / 1 serwera”, gdy masz absolutną pewność, że problemy z wydajnością wynikają z ograniczeń sprzętowych, a nie tylko z mniejszego projektu / implementacji.

Albo, jak sądzę, innym powodem, dla którego niektórzy ludzie przechodzą na rozproszone bazy danych, jest to, że nie są przygotowani na płacenie dużych (lub jakichkolwiek) pieniędzy w opłatach licencyjnych i chcą porzucić SQL jako świadomy wybór, aby wymienić niski koszt zwiększonej złożoności aplikacji. Całkowicie uzasadniony powód, jeśli jesteś startupem programistycznym, ale zwykle nie dotyczy sektora korporacyjnego.

Aaronaught
źródło
+1 - tak naprawdę nie zastanawiałem się nad NoSQL, ale i tak jest to pomocne. Dzięki.
VirtuosiMedia,
1

Istnieją trzy główne typy konfiguracji replikacji dla baz danych:

  • Master-Slave
  • Master-Master
  • Zgoda

Przykład Master-Slave: MySQL master + MySQL slaves, MongoDB

Przykład Master-Master: CouchDB, Cassandra, Riak

Przykład konsensusu: ScalienDB

...aby wymienić tylko kilka.

Mają różne cechy. Konfiguracje master-slave pozwalają węzłom slave dogonić master z maksymalną szybkością, jednocześnie bardzo szybko obsługując żądania odczytu, podczas gdy serwer master jest odpowiedzialny za integralność danych. Ponieważ wszystkie zapisy trafiają do mastera, nigdy nie ma blokady rywalizacji, ponieważ jeden stosunkowo powolny pisarz blokuje wiele czytników, ale z drugiej strony serwery podrzędne są ostatecznie spójne i nie dostajesz gwarancji izolacji transakcji, które byś miał z czytania tylko od mistrza. (dalsze czytanie; ACID vs BASE, poziomy izolacji transakcji, replikacja bazy danych, MVCC / Izolacja: migawka, replikacja transakcyjna)

Master-Master zawsze zezwala na zapisy, abyś miał wiele autorytetów w tym, co jest prawdą. Może to, ale nie musi stanowić problemu, w zależności od tego, co robi twoja aplikacja, ale jeśli napiszesz sprzeczne dane, możesz następnym razem uzyskać wiele wyników przy następnym czytaniu tego klucza / wiersza / kolumny, które będziesz musiał scalić z logiką aplikacji i zapisz z powrotem do bazy danych. (dalsza lektura: twierdzenie CAP, replikacja CouchDB, replikacja Riaka, spójne haszowanie, Bitcask i StormDB, kworum w / MongoDB w sprawie podziału sieci, strategie rozwiązywania scalania)

Bazy danych oparte na konsensusie z replikacją między węzłami, takie jak Scalien, zawsze byłyby spójne w przypadku zapisów, ale kosztem wymiany wielu wiadomości przed potwierdzeniem zapisu. Nie stanowi to większego problemu, jeśli masz szybki Ethernet i nie musisz zapisywać na dysku przed ACKingiem, co nie będzie potrzebne, jeśli twoje minimum trzy serwery znajdują się na różnych szafach serwerowych z osobnymi zasilaczami (jeden umiera; pozostali dwaj upewniają się, że zapisali na dysku). (dalsze czytanie; PAXOS, PAXOS COMMIT, zatwierdzanie dwufazowe z transakcjami rozproszonymi, zatwierdzanie trójfazowe)

Inne dalsze czytanie: (książka: „Elementy przetwarzania rozproszonego”, zegary wektorowe, wektory wersji, wektory macierzowe, zegary logiczne, algorytm piekarniczy, zegary drzewa interwałowego, aktorzy i programowanie reaktywne i reaktory, programowa pamięć transakcyjna, transakcje, AKKA, Stact, błędy przetwarzania rozproszonego, protokoły plotek, rozszerzenia protokołu plotek anty-entropii Cassandry, rozproszone tabele skrótów, dokumenty na temat scalania danych w rozproszonym otoczeniu, architektura ZooKeeper, prezentacja InfoQ na temat „protokołu asynchronicznego”, architektura HBase, papier MapReduce, papier Amazon Dynamo które rozpoczęło wszystkie funkcje NoSQL, kolejkowanie, klastrowanie o wysokiej dostępności przez królikmq)

Mam nadzieję, że dałem trochę do myślenia :). Możesz śledzić mnie na Twitterze @henrikfeldt, jeśli chcesz też tweetów na ten temat.

Henrik
źródło
1

OK, oto kolejny punkt widzenia na skalowalność.

Omówmy, co to znaczy, że dane są danymi, co oznacza zachowanie i logika aplikacji.

Zwykle, gdy ktoś zapuszcza się w krainę aplikacji korporacyjnych i tym podobnych, miałby kontakt z ideą nakładania warstw. Oczywiście nakładanie warstw jest wszędzie w komputerach, takich jak stos sieciowy (model ISO), grafika (Photoshop) lub SOA (usługi mogą wywoływać rodzeństwo lub dzieci, ale nigdy rodziców).

Jednak szczególnym rodzajem warstw, które były nadużywane bez względu na to, co kiedykolwiek było, jest „GUI”, „warstwa logiki biznesowej”, a następnie „warstwa dostępu do danych”. Chodzi mi o to, że pomysł jest dobry, podobnie jak komunizm, ale w rzeczywistości tak nie jest.

Zobaczmy, dlaczego. Argument, który zamierzam użyć, dotyczy sprzężenia; punkty z jednej warstwy, która dotyka punktów na innej warstwie. Za każdym razem, gdy zaczynasz tworzyć aplikację warstwową aka z warstwami w domyślnym trybie przedsiębiorczości, w który wchodzą ludzie, tworzą oni tak wiele punktów kontaktu między warstwami.

W istocie chodzi o to, że warstwy są wymienne; ale nie są! Dlaczego? Ze względu na wszystkie połączenia strony wywoławczej.

Zamiast tego zobacz, dlaczego sieć jest oddzielona! Ponieważ interfejs jest strumieniem bajtów nad pojedynczym wskaźnikiem pliku, który wskazuje na otwarte gniazdo! Wszystkie warstwy w modelach ISO są podobne do tego, co wzorzec projektowy zwany „łańcuchem odpowiedzialności” ma na celu zorientowanie obiektowe! Każda warstwa otacza podstawową warstwę, nie znając semantyki danych w tej warstwie.

Gdy pakiet danych zbliża się do Ethernetu i nieprzetworzonych sygnałów elektrycznych na dole, jest ciągle owijany warstwami, które znają tylko swoją specyficzną kopertę wiadomości, swoją własną „partię bajtów”, którą może wysłać; i nic więcej. Nie musi zmieniać ścieżek wywołań w zależności od zawartości pakietu.

Porównaj to z poziomem n, w którym musiałbyś zmienić ścieżkę połączeń w warstwach aplikacji podczas „połączenia” przechodzącego przez twoje warstwy w drodze do bazy danych - na przykład „klienci złota” są polimorficznie nadzbiorem „zwykłych klientów” dlatego, że używamy „tabeli na podklasę”, musimy wiedzieć o tym teraz, gdy dane (byt) przemierzają warstwy; zarówno w tak zwanej „warstwie logiki biznesowej”, jak i w warstwie danych, która faktycznie oszczędza.

Nie jest skalowalny ani optymalny z punktu widzenia komputerów.

Dlaczego nie jest skalowalny? Ponieważ architektura jest sprzężona, a następnie nadal znajdujesz się w tej samej starej bazie danych, którą próbujesz skalować do wielu węzłów! Ponieważ jednak potrzebujesz do tego ACID, a także trzeciego podmiotu (obiektu danych), musisz mieć je w jednej bazie danych, która dokonuje transakcji!

Righty, a więc z tym zakazem; jakie są inne sposoby?

Istnieje znienawidzony skrót o nazwie „SOA”, tj. Architektura zorientowana na usługi. Oczywiście, Tomas Erls na świecie , chciałby zaimplementować wszystkie swoje warstwy, ale zamiast XML i SOAP.

Z wszystkich powyższych powodów jest to niewłaściwa droga, ponieważ łączysz się z tymi serwerami proxy XML tak, jakbyś łączył się z warstwami aplikacji, jak wyjaśniono powyżej.

Zamiast tego używaj wiadomości i pozwól, aby cokolwiek implementowało dla nich funkcjonalność, słuchaj ich. Twoja powierzchnia serwisowa staje się listą wiadomości, które możesz wysłać, a operacji nie połączyłeś z fasadą usługi; i nawet nie musisz wiedzieć, która aplikacja lub punkt końcowy implementuje te operacje, ponieważ wszystko, co robisz, to publikowanie komunikatu, który jakiś inny mechanizm routingu skieruje do właściwego konsumenta!

Ponieważ oddzieliłeś fasady usług od faktycznych operacji, które chcesz wykonać, możesz teraz dodać wiele usług; tak właśnie robi Netflix. Obejrzyj te prezentacje: http://www.slideshare.net/adrianco/global-netflix-platform . http://www.slideshare.net/adrianco/global-netflix-platform . Oni są dobrzy!

Henrik
źródło
0

Istnieje nowa baza danych SQL (ACID) w wersji beta, która ma mieć elastyczne właściwości skalowania. Obecnie trwa bezpłatny program w wersji beta i sugeruję, abyś spojrzał, nazywa się NuoDB.

Najwyraźniej z łatwością przewyższa MySQL nawet na maszynie z jednym wątkiem, ale skaluje się szczęśliwie do ponad 70 wystąpień w niektórych testach porównawczych.

Dibbeke
źródło
Pojedynczy wątek? Jak zatem jest to odpowiedni punkt odniesienia?
Henrik