Mam dystrybuowane/stowarzyszonej bazy danych posiada następującą strukturę:Optymalizacja przepustowość sieci nad rozproszonymi pracy agregacji bazodanowych
- Bazy danych są rozłożone w trzech lokalizacjach geograficznych („węzły”)
- wielu baz danych są skupione na siebie węzeł
- Relacyjne bazy danych to połączenie PostgreSQL, MySQL, Oracle i MS SQL Server; nie-relacyjnych baz danych albo MongoDB lub Cassandro
- Luźne sprzęgającą wewnątrz każdego węzła i przez Federacji węźle odbywa się za pomocą RabbitMQ, przy czym każdy węzeł działa maklera RabbitMQ
ja wykonawczego tylko do odczytu agregacji między węzłami system zadań dla zadań, które obejmują federację węzłów (tj. dla zadań, które nie są lokalne dla węzła). Te zadania wykonują tylko kwerendy "get" - nie modyfikują baz danych. (Jeśli wyniki zadań mają pochodzić z jednej lub więcej baz danych, to jest to realizowane przez oddzielne zadanie, które nie jest częścią między-węzłowego systemu zadań, który próbuję zoptymalizować.) Moim celem jest zminimalizowanie przepustowość sieci wymagana przez te zadania (najpierw w celu zminimalizowania szerokości pasma między węzłami/WAN, a następnie w celu zminimalizowania przepustowości wewnątrz węzła/sieci LAN); Zakładam jednakowy koszt dla każdego łącza WAN i inny jednolity koszt dla każdego łącza LAN. Miejsca pracy nie są szczególnie wrażliwe na czas. Wykonuję pewne równoważenie obciążenia procesora w węźle, ale nie między węzłami.
Ilość danych przesyłanych przez sieć WAN/LAN dla zadań agregacji jest niewielka w stosunku do liczby zapisów do bazy danych, które są lokalne dla klastra lub określonej bazy danych, więc nie byłoby praktycznie w pełni dystrybuować bazy danych przez federację.
Podstawowy algorytm używać do minimalizacji przepustowość sieci jest:
- Biorąc pod uwagę pracę, która działa na zbiorze danych, które są rozłożone w całej federacji, węzeł menedżer wysyła wiadomość do każdego z pozostałych węzłów zawiera odpowiednie zapytania do bazy danych.
- Każdy węzeł uruchamia zestaw zapytań, kompresuje je za pomocą programu gzip, buforuje je i wysyła ich skompresowane rozmiary do węzła menedżera.
- Menedżer przesuwa się do węzła zawierającego wiele danych (w szczególności do maszyny w klastrze, która ma najwięcej danych i która ma bezczynne rdzenie); żąda reszty danych z pozostałych dwóch węzłów i innych maszyn w klastrze, a następnie uruchamia zadanie.
Gdy jest to możliwe, zadania wykorzystują metodę dziel i rządź, aby zminimalizować ilość wymaganych kolokacji danych. Na przykład, jeśli zadanie musi obliczyć sumy wszystkich wartości sprzedaży w federacji, wówczas każdy węzeł lokalnie oblicza swoje sumy sprzedaży, które następnie są agregowane w węźle menedżera (zamiast kopiowania wszystkich nieprzetworzonych danych sprzedaży do węzła menedżera) . Czasami jednak (np. Podczas łączenia między dwiema tabelami, które znajdują się w różnych węzłach) potrzebne jest kolokacja danych.
Pierwszą rzeczą, którą zrobiłem, aby to zoptymalizować, było zsumowanie miejsc pracy i uruchomienie zagregowanych zadań w dziesięciominutowych epokach (wszystkie maszyny działają z NTP, więc mogę być w miarę pewna, że "co dziesięć minut" oznacza to samo rzecz w każdym węźle). Celem jest udostępnienie tych samych danych dwóm pracownikom, co zmniejsza całkowity koszt transportu danych.
- Przy dwóch zadaniach, które wysyłają zapytania do tej samej tabeli, generuję zestaw wyników każdego zadania, a następnie przechodzę przez punkt przecięcia dwóch zestawów wyników.
- Jeśli oba zadania mają być uruchamiane w tym samym węźle, wówczas koszt transferu sieciowego jest obliczany jako suma dwóch zestawów wyników minus przecięcie dwóch zestawów wyników.
- Te dwa zestawy wyników są przechowywane w tymczasowych tabelach PostgreSQL (w przypadku danych relacyjnych) lub tymczasowo w kolekcjach Cassandra columnfamilies/MongoDB (w przypadku danych nosql) w węźle wybranym do uruchamiania zadań; oryginalne kwerendy są następnie wykonywane w odniesieniu do połączonych zestawów wyników, a dostarczane dane są do poszczególnych zadań. (Ten krok jest wykonywany tylko w połączonych zestawach wyników, poszczególne dane zestawu wyników są po prostu dostarczane do jego pracy bez wcześniejszego przechowywania na tymczasowych tabelach/rodzinach kolumn/kolekcjach.)
Powoduje to poprawę przepustowości sieci, ale ja zastanawiam się, czy istnieje framework/biblioteka/algorytm, który poprawiłby się w tym zakresie. Jedną z opcji, którą rozważałem, jest buforowanie zestawów wyników w węźle i uwzględnianie zbuforowanych zestawów wyników przy określaniu przepustowości sieci (tj. Próba ponownego użycia zestawów wyników między zadaniami, oprócz bieżącego zestawu wcześniej zaplanowanych, współlokowanych zadań, tak aby np. zadanie uruchomione w jednej 10-minutowej epoce może użyć zbuforowanego zestawu wyników z poprzedniego 10-minutowego zestawu wyników), ale jeśli zadania nie używają dokładnie tych samych zestawów wyników (tj. jeśli nie używają identycznych klauzul dotyczących miejsc), to nie znam ogólnego algorytm celu, który wypełniłby luki w zestawie wyników (na przykład, gdyby zestaw wyników używał klauzuli "gdzie N> 3" i innego zadania wymaga zestawu wyników z klauzulą "gdzie N> 0", to jaki algorytm mógłbym użyć do określić, że muszę wziąć unię oryginalnego zestawu wyników, a zestaw wyników z klauzulą "gdzie N> 0 I N < = 3") - Mógłbym spróbować napisać własny algorytm, aby to zrobić, ale wynik byłby buggy bezużyteczny bałagan. Chciałbym również określić, kiedy dane w pamięci podręcznej są nieaktualne - najprostszym sposobem jest porównanie datownika z pamięci podręcznej z ostatnio zmodyfikowanym znacznikiem czasu w tabeli źródłowej i zastąpienie wszystkich danych, jeśli znacznik czasu się zmienił, ale najlepiej Chciałbym móc aktualizować tylko wartości, które uległy zmianie w przypadku znaczników czasu dla poszczególnych wierszy lub porcji.
Czy łatwiej byłoby w pełni rozdzielić tabele w pełni do każdej witryny, a nie próbować obsługiwać fragmentów z częściowych klauzul? Miejsce na dysku jest tanie, ale zależy to od tego, jak często zmieniają się dane, a jak wąskie są twoje predykaty, czy to zmniejszy ruch w sieci. – rlb
@rlb Problem polega na tym, że w każdym klastrze jest dużo działań zapisu, a więc w pełni rozproszone tabele oznaczałyby, że ta aktywność zapisu musiałaby propagować do każdego klastra, nawet jeśli nie jest potrzebna. Na przykład jedna baza danych to finansowa baza danych z cenami akcji, co oznacza, że istnieje ** lot ** zapisów bazy danych. Sfederowane zadania prawdopodobnie potrzebują tylko migawki tych danych co najwyżej co godzinę, co stanowi ułamek przepustowości sieci, która byłaby potrzebna do propagacji danych dla każdej aktualizacji zasobów do każdego klastra. –
Dobrze rozumiem problem z głośnością. Czy masz kontrolę nad tym, co jest przesyłane przez przewód? Przełączyliśmy się z wiersza na kolumnę dla zestawów wyników i współczynniki kompresji poszły w górę, więc ta mighht to prosta wygrana, niskie ryzyko, ale nie to, o co dokładnie prosisz. Będziemy polować w biurze, szukając czegoś na twoje aktualne pytanie, ale głównie pracujemy nad optymalizacją jako rozproszone sprzężenie, które, jak wspomniałeś, może być flakowane, jeśli nie zostanie wykonane perfekcyjnie. – rlb