Która baza danych mogłaby obsłużyć przechowywanie miliardów / trylionów rekordów?

75

Chcemy opracować narzędzie do przechwytywania i analizy danych przepływu netto, z których zbieramy ogromne ilości. Każdego dnia rejestrujemy około ~ 1,4 miliarda rekordów przepływu, które wyglądałyby tak w formacie json:

{
   "tcp_flags": "0",
   "src_as": "54321",
   "nexthop": "1.2.3.4",
   "unix_secs": "1352234521",
   "src_mask": "23",
   "tos": "0",
   "prot": "6",
   "input": "105",
   "doctets": "186",
   "engine_type": "0",
   "exaddr": "2.3.4.5",
   "engine_id": "2",
   "srcaddr": "9.8.7.6",
   "dst_as": "12345",
   "unix_nsecs": "752265174",
   "sysuptime": "2943529544",
   "dst_mask": "24",
   "dstport": "80",
   "last": "2943523241",
   "srcport": "52672",
   "dpkts": "4",
   "output": "111",
   "dstaddr": "6.5.4.3",
   "first": "2943517993"
}

Chcielibyśmy mieć możliwość szybkiego wyszukiwania (mniej niż 10 sekund) zestawu danych, najprawdopodobniej w wąskich przedziałach czasu (10-30 interwałów miętowych). Chcemy również zindeksować większość punktów danych, abyśmy mogli szybko wyszukać każdy z nich. Chcielibyśmy również mieć aktualny widok danych podczas wyszukiwania. Byłoby wspaniale pozostać w świecie open source, ale nie jesteśmy przeciwni szukaniu autorskich rozwiązań dla tego projektu.

Chodzi o to, aby przechowywać około jednego miesiąca danych, co stanowi ~ 43,2 miliarda rekordów. Z grubsza szacuje się, że każdy rekord zawiera około 480 bajtów danych, co odpowiada około 18,7 terabajtom danych w ciągu miesiąca, a może trzy razy więcej niż w przypadku indeksów. W końcu chcielibyśmy zwiększyć pojemność tego systemu do przechowywania bilionów rekordów.

Oceniliśmy (bardzo zasadniczo) bazę kanapy, cassandrę i mongodb, na ile to możliwe, kandydatów do tego projektu, jednak każdy z nich proponuje własne wyzwania. W przypadku bazy danych indeksowanie odbywa się w odstępach czasu, a nie podczas wstawiania danych, więc widoki nie są aktualne, wtórne indeksy Cassandry nie są bardzo skuteczne w zwracaniu wyników, ponieważ zwykle wymagają skanowania całego klastra w poszukiwaniu wyników, a mongodb wygląda obiecująco, ale wydaje się o wiele trudniejsze do skalowania, ponieważ jest to master / slave / shaged. Niektóre inne kandydatury, które planujemy ocenić, to elasticsearch, mysql (nie jestem pewien, czy to w ogóle ma zastosowanie) i kilka relacyjnych baz danych zorientowanych na kolumny. Będziemy wdzięczni za wszelkie sugestie lub doświadczenia z prawdziwego świata.

jakoś tak
źródło
Komentarze nie są przeznaczone do rozszerzonej dyskusji; ta rozmowa została przeniesiona do czatu .
Paul White

Odpowiedzi:

57

W firmie, dla której pracuję, mamy do czynienia z podobną ilością danych (około 10 TB danych z możliwością wyszukiwania w czasie rzeczywistym). Rozwiązujemy to za pomocą Cassandry i chciałbym wspomnieć o kilku pomysłach, które pozwolą ci wyszukiwać O (1) w bazie danych wielu TB. Nie jest to jednak specyficzne dla bazy danych Cassandra, można jej również używać z innymi bazami danych.

Teoria

  • Odetnij swoje dane. Nie ma możliwości, aby pojedynczy serwer w wiarygodny i realistyczny sposób przechowywał taką ilość danych.
  • Przygotuj się na awarie sprzętowe i awarie całego węzła, powiel dane.
  • Zacznij korzystać z wielu serwerów zaplecza od samego początku.
  • Używaj wielu tańszych serwerów towarowych w porównaniu do wysokiej klasy serwerów o wysokiej wydajności.
  • Upewnij się, że dane są równo rozłożone na odłamki.
  • Poświęć dużo czasu na planowanie zapytań. Uzyskaj API z zapytań, a następnie dokładnie zaprojektuj tabele. To najważniejsze i długotrwałe zadanie.
  • W Cassandrze możesz zaprojektować złożony klucz kolumny i uzyskać dostęp do tego klucza w O (1). Poświęć czas na ich pracę. Będzie to służyć do uzyskiwania dostępu do rekordów z możliwością wyszukiwania zamiast indeksu dodatkowego.
  • Skorzystaj z szerokich rzędów. Przydają się do przechowywania znaczników czasu.
  • Nigdy nie wykonuj pełnego skanowania ani żadnej operacji większej niż O (Log N) na takim woluminie. Jeśli potrzebujesz czegoś więcej niż O (Log N), przenieś takie operacje do algorytmów Map-Reduce.

Ćwiczyć

  • Nie marnuj czasu na tworzenie obrazów systemu operacyjnego lub instalowanie serwerów na fizycznych urządzeniach. Użyj dostawców chmurowych do szybkiego prototypowania. Pracowałem z Amazon EC2 i mogę go bardzo polecić ze względu na prostotę, niezawodność i szybkość prototypowania.
  • Komputery z systemem Windows działają wolniej podczas uruchamiania i zużywają znacznie więcej zasobów w stanie bezczynności. Rozważ użycie systemu operacyjnego opartego na Uniksie. Osobiście uważam, że serwer Ubuntu to niezawodny system operacyjny, ale poza tym w askubuntu istnieje całkiem niezła społeczność
  • Pomyśl o sieciach, węzły powinny być idealnie blisko siebie, aby umożliwić szybkie plotkowanie i wymianę metadanych.
  • Nie wchodź w skrajne przypadki: naprawdę szerokie rzędy kolumn lub wyjątkowo długie rodziny kolumn (tabele). Najlepszą wydajność osiąga się w rozsądnych granicach - jeśli db obsługuje z założenia tyle N wierszy, nie oznacza to, że działa dobrze.
  • Nasze wyszukiwanie zajmuje około 3-5 sekund, wiele wynika z pośrednich węzłów między interfejsem użytkownika a bazą danych. Zastanów się, jak przybliżyć żądania do bazy danych.
  • Użyj modułu równoważenia obciążenia sieciowego. Wybierz ustalony. Używamy HAProxy, który jest prosty, ale bardzo szybki. Nigdy nie miałem z tym problemów.
  • Wolę prostotę od skomplikowanych rozwiązań.
  • Szukaj darmowych rozwiązań typu open source, chyba że masz wsparcie z budżetu wielkości korporacji. Gdy przejdziesz na więcej niż kilka serwerów, koszty infrastruktury mogą wzrosnąć w górę.

Nie pracuję dla Amazon i nie mam żadnych relacji z zespołami HAProxy i Ubuntu. To jest osobista opinia, a nie jakakolwiek promocja.

oleksii
źródło
5
Jestem prawie pewien, że wyszukiwanie O (1) jest niemożliwe oprócz wyjątkowo trywialnych / bezużytecznych przypadków.
Fitzsimmons
2
Nie obrażaj się, ale powiedz to Google. Wyszukiwanie O (1) jest możliwe w skali PB przy starannym zaprojektowaniu.
oleksii
9
@oleksii Miliardy budżetów Google nie stanowią rozsądnego porównania do losowania.
Mark Storey-Smith
4
Mogę połączyć 3 poprzednie komentarze zO(1) search <=> unbounded storage space <=> unlimited supply of cash
ypercubeᵀᴹ
3
O (1) wyszukiwanie pojedynczego rekordu można przeprowadzić za pomocą liniowej tabeli skrótów. . Nie daje to jednak żadnej wydajności w sekwencyjnym wyszukiwaniu (dla zakresów). Do tego potrzebny jest jakiś wariant struktury BTree, którym jest O (log n) dla pojedynczego elementu.
ConcernedOfTunbridgeWells
41

Gdybym chciał umieścić to w SQL Server, zasugerowałbym tabelę w stylu:

CREATE TABLE tcp_traffic
(
    tcp_traffic_id bigint constraint PK_tcp_traffic primary key clustered IDENTITY(1,1)
    , tcp_flags smallint    /* at most 9 bits in TCP, so use SMALLINT */
    , src_as int        /* Since there are less than 2 billion A.S.'s possible, use INT */
    , netxhop bigint    /* use a big integer for the IP address instead of storing
                             it as dotted-decimal */
    , unix_secs bigint  
    , src_mask int      /* an assumption */
    , tos tinyint       /* values are 0-255, see RFC 791 */
    , prot tinyint      /* values are 0-255, see RFC 790 */
    , input int         /* an assumption */
    , doctets int       /* an assumption */
    , engine_type int   /* an assumption */
    , exaddr bigint     /* use a big integer for the IP address instead of storing
                             it as dotted-decimal */
    , engine_id int     /* an assumption */
    , srcaddr bigint    /* use a big integer for the IP address instead of storing
                             it as dotted-decimal */
    , dst_as int        /* Since there are less than 2 billion A.S.'s possible, use INT */
    , unix_nsecs bigint /* an assumption */
    , sysuptime bigint  /* an assumption */
    , dst_mask int      /* an assumption */
    , dstport smallint  /* ports can be in the range of 0 - 32767 */
    , [last] bigint     /* an assumption */
    , srcport smallint  /* ports can be in the range of 0 - 32767 */
    , dpkts int         /* an assumption */
    , output int        /* an assumption */
    , dstaddr bigint    /* use a big integer for the IP address instead of storing
                            it as dotted-decimal */
    , [first] bigint    /* an assumption */
);

Powoduje to całkowite szacunkowe zapotrzebowanie na miejsce do przechowywania pojedynczej tabeli, bez dalszych indeksów 5,5 TB dla rekordów 43,2 zapisów pszczół (twoje określone wymaganie). Jest to obliczane jako 130 bajtów dla samych danych, plus 7 bajtów na wiersz narzutu, plus 96 bajtów na stronę narzutu. SQL Server przechowuje dane na stronach 8 KB, pozwalając na 59 wierszy na stronę. Odpowiada to 732,203,390 stronom za jeden miesiąc danych.

SQL Server lubi zapisywać na dysku w 8-stronicowych porcjach (64 KB), co odpowiada 472 wierszom na fizyczne operacje we / wy. Ponieważ co sekundę generowanych jest 16,203 rekordów przepływu, będziesz potrzebować minimalnej szybkości we / wy 34 IOps, gwarantowanej co sekundę. Chociaż samo w sobie nie jest to ogromna ilość, inne wejścia / wyjścia w systemie (SQL Server i inne) nigdy nie muszą naruszać tej wymaganej szybkości operacji we / wy. Dlatego musisz zaprojektować system zdolny do uzyskania co najmniej rzędu rzędów wielkości więcej operacji IOps lub 340 operacji IOps o przedłużonej trwałości - staram się oszacować, że potrzebujesz 2 rzędów wielkości bardziej zrównoważonych operacji IOps, aby zagwarantować przepustowość.

Zauważysz, że nie przechowuję adresów IP w ich postaci dziesiętnej z kropkami. Oszczędza to ogromną ilość miejsca (7 bajtów na adres), a także sprawia, że ​​indeksowanie, pobieranie, sortowanie i porównywanie adresów IP jest znacznie bardziej wydajne. Minusem jest to, że przed zapisaniem należy przekonwertować adresy IP z kropkami dziesiętnymi na 8-bajtowe liczby całkowite i powrócić do adresów IP z kropkami dziesiętnymi w celu wyświetlenia. Kod do zrobienia tego jest trywialny, jednak szybkość tego rzędu doda znaczną część kosztów przetwarzania do każdego przetwarzanego wiersza przepływu - możesz chcieć wykonać ten proces konwersji na fizycznie innym komputerze niż SQL Server.

Omówienie wymaganych indeksów to zupełnie osobna sprawa, ponieważ nie wymieniono żadnych szczegółowych wymagań. Projekt tej tabeli będzie przechowywał wiersze przepływu w fizycznej kolejności, w jakiej są odbierane przez SQL Server, tcp_traffic_idpole jest unikalne dla każdego rekordu i umożliwia sortowanie wierszy według kolejności, w której zostały zarejestrowane (w tym przypadku najprawdopodobniej odnosi się jeden do jednego do czasu zdarzenia flow).

Max Vernon
źródło
4
Prawdopodobnie użyłbym binary(4)lub binary(16). 4 bajty / wiersz sumują się do dużej ilości miejsca po pomnożeniu przez 1 000 000 000 000.
Jon Seigel
2
Numery portów mają zakres 0–65535, więc możesz z nich korzystać, SMALLINTale musi tam być również procedura konwersji.
ypercubeᵀᴹ
7
@MrTelly Nie zgadzam się. Wykonanie tego w programie SQL Server jest kosztowne tylko wtedy, gdy potrzebujesz wysokiej dostępności lub dużych przełączeń awaryjnych. W przypadku solidnego magazynu danych, z którym naprawdę łatwo jest żyć, SQL Server doskonale nadaje się do tego. Wszystkie systemy stają się bardzo drogie (i skomplikowane), jeśli potrzebne jest HA.
samsmith
2
IMO, SQL Server zdecydowanie może przechowywać dane; Nadal nie jestem pewien, czy jest to właściwe rozwiązanie do rozwiązania części analitycznej projektu, głównie dlatego, że nie znam się wystarczająco na innych rozważanych systemach.
Jon Seigel
3
@MrTelly Istnieją dwa koszty: a) Pamięć dyskowa (dla 5-8 TB, w zależności od miejsca zajmowanego przez indeksy) b) Pamięć RAM (do obsługi zapytań, buforowania indeksów). Aby to zrobić monolitycznie, zwykle wykonuje się to przy użyciu dużej macierzy RAID10 lub SAN. Należy jednak pamiętać, że dzielenie na fragmenty z pewnością można wykonać i może ono pozwolić na użycie logiki na poziomie aplikacji do podziału obciążenia na wiele serwerów SQL. Może to pozwolić na użycie tanich serwerów o pojemności 0,5-2 TB każdy, a być może nawet na darmową wersję SQL Server. (Należy pamiętać, że dzielenie na fragmenty jest ogólną koncepcją, często odbywa się na poziomie aplikacji i ma zastosowanie do dowolnej metody trwałości)
samsmith
5

Polecam HBase . Możesz przechowywać wszystkie nieprzetworzone dane w jednej lub więcej tabel HBase, w zależności od tego, czego potrzebujesz do zapytania. HBase może obsługiwać duże zestawy danych i dokonuje automatycznego dzielenia fragmentów regionu.

Ponadto, jeśli dobrze projektujesz klucze wierszy, możesz uzyskać niezwykle szybkie, nawet zapytania O (1). Pamiętaj, że jeśli pobierasz duży zestaw danych, nadal będzie on wolny, ponieważ pobieranie danych jest operacją O (n).

Ponieważ chcesz zapytać w każdym polu, zalecam utworzenie unikalnej tabeli dla każdego z nich. Przykład danych src_address zawiera tabela wyglądającą tak:

1.2.3.4_timestamp1 : { data }
1.2.3.4_timestamp2 : { data }

Jeśli więc chcesz wysłać zapytanie o wszystkie dane w 1.2.3.4, zaczynając od 27 marca 12:00 do 27 marca 00:01, możesz wykonać skanowanie zakresu z określonymi wierszami start i stop.

IMHO, projekt klucza wiersza jest najważniejszą częścią korzystania z HBase - jeśli dobrze go zaprojektujesz, będziesz w stanie wykonywać szybkie zapytania ORAZ przechowywać duże ilości danych.

Suman
źródło
3

Powiedział to :

... nie jesteśmy przeciwni szukaniu autorskich rozwiązań dla tego projektu

Sugeruję rozważenie bazy danych IBM Informix + bazy danych TimeSeries . W przeciwieństwie do tego, co mówią niektórzy, Informix żyje i ma się bardzo dobrze. Ostatnia wersja została wydana w zeszłym miesiącu (marzec / 2013, wersja 12.10).

TimeSeries jest jak „wtyczka” (bez kosztów) zdolna poradzić sobie w sytuacjach takich jak Twoja.
I możesz go używać w produkcji z bezpłatną wersją bazy danych Informix ( edycja Innovator-C ). (oczywiście, tylko w celu oceny części technicznych, ponieważ darmowa wersja ma wiele ograniczonych zasobów)

Tutaj możesz sprawdzić plik PDF z testem porównawczym, który można wykorzystać jako odniesienie. Oto dwie prezentacje z bardziej technicznymi przykładami: przewodnik dla manekinów i inne wskazówki

Nie mam osobistego doświadczenia z TimeSeries , więc nie mogę się zgodzić, że będzie to „rozwiązanie”, tylko sugestia do oceny.

ceinmart
źródło
2

Drugim zaleceniem jest przyjrzenie się Informix TimeSeries. Literatura IBM twierdzi, że TimeSeries może przechowywać tego rodzaju informacje w 1/5 miejsca i wykonywać 5 razy szybciej niż tradycyjne tabele relacyjne.

Dodatkowymi korzyściami byłby interfejs tabeli wirtualnej, który może sprawić, że dane TimeSeries będą wyglądać jak tradycyjne tabele relacyjne dla użytkownika końcowego (upraszczając tworzenie aplikacji, a jednocześnie czerpać korzyści z TimeSeries), prosty HA z węzłami HDR, które teraz obsługują dane TimeSeries w wersji 12.1 i integracja danych TimeSeries z Informix Warehouse Accelerator, które mogą być wykorzystane do przyspieszenia skomplikowanych raportów hurtowni danych oraz możliwość prototypowania rozwiązania TimeSeries w Informix przy użyciu darmowych wersji Informix Developer lub Innovator-C.

Andrzej
źródło