In welcher Datenbank können Milliarden / Billionen von Datensätzen gespeichert werden?


75

Wir planen die Entwicklung eines Tools zur Erfassung und Analyse von Netflow-Daten, von denen wir enorme Mengen sammeln. Jeden Tag erfassen wir ungefähr 1,4 Milliarden Flow-Datensätze, die im JSON-Format wie folgt aussehen würden:

{
   "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"
}

Wir möchten in der Lage sein, den Datensatz schnell zu durchsuchen (weniger als 10 Sekunden), höchstwahrscheinlich über kurze Zeiträume (Intervalle von 10 bis 30 Minuten). Wir möchten auch den Großteil der Datenpunkte indizieren, damit wir jede einzelne schnell durchsuchen können. Wir möchten auch eine aktuelle Ansicht der Daten haben, wenn Suchen ausgeführt werden. Es wäre großartig, in der Open Source-Welt zu bleiben, aber wir sind nicht dagegen, proprietäre Lösungen für dieses Projekt zu suchen.

Die Idee ist, ungefähr einen Monat Daten zu speichern, was ungefähr 43,2 Milliarden Datensätzen entspricht. Eine grobe Schätzung, dass jeder Datensatz ungefähr 480 Datenbytes enthalten würde, würde ~ 18,7 Terabytes Daten in einem Monat entsprechen, und vielleicht dreimal so viel wie bei Indizes. Schließlich möchten wir die Kapazität dieses Systems erweitern, um Billionen von Datensätzen zu speichern.

Wir haben Couchbase, Cassandra und Mongodb (im Grunde genommen) als mögliche Kandidaten für dieses Projekt bewertet, jedoch schlägt jeder seine eigenen Herausforderungen vor. Mit couchbase wird die Indizierung in Intervallen und nicht während des Einfügens der Daten durchgeführt, sodass die Ansichten nicht auf dem neuesten Stand sind. Die Sekundärindizes von cassandra sind nicht sehr effizient bei der Rückgabe von Ergebnissen, da sie normalerweise das Scannen des gesamten Clusters nach Ergebnissen erfordern Es scheint weitaus schwieriger zu skalieren zu sein, da es Master / Slave / Sharded ist. Einige andere Kandidaten, die wir evaluieren möchten, sind elasticsearch, mysql (nicht sicher, ob dies überhaupt anwendbar ist) und einige spaltenorientierte relationale Datenbanken. Anregungen oder Erfahrungen aus der realen Welt wäre dankbar.


Kommentare sind nicht für eine längere Diskussion gedacht. Diese Unterhaltung wurde in den Chat verschoben .
Paul White

Antworten:


57

In einem Unternehmen, für das ich arbeite, haben wir es mit einer ähnlichen Datenmenge zu tun (etwa 10 TB Echtzeit-Suchdaten). Wir lösen das mit Cassandra und ich möchte einige Ideen erwähnen, mit denen Sie O (1) in einer Datenbank mit mehreren TB suchen können. Dies ist jedoch nicht spezifisch für Cassandra db. Sie können es auch für andere db verwenden.

Theorie

  • Shard deine Daten. Auf keinen Fall kann ein einzelner Server ein solches Datenvolumen zuverlässig und realistisch speichern.
  • Seien Sie bereit für Hardwarefehler und Ausfälle ganzer Knoten, duplizieren Sie die Daten.
  • Beginnen Sie von Anfang an mit der Verwendung vieler Back-End-Server.
  • Verwenden Sie viele billigere Standardserver im Vergleich zu Hochleistungsservern der Spitzenklasse.
  • Stellen Sie sicher, dass die Daten gleichmäßig auf die Shards verteilt sind.
  • Nehmen Sie sich viel Zeit für die Planung Ihrer Abfragen. Leiten Sie die API aus den Abfragen ab und entwerfen Sie die Tabellen sorgfältig. Dies ist die wichtigste und langwierigste Aufgabe.
  • In Cassandra können Sie einen zusammengesetzten Spaltenschlüssel entwerfen und in O (1) auf diesen Schlüssel zugreifen. Verbringen Sie Zeit damit, daran zu arbeiten. Dies wird verwendet, um auf durchsuchbare Datensätze statt auf den Sekundärindex zuzugreifen.
  • Nutzen Sie breite Reihen. Sie sind nützlich zum Speichern von Ereignissen mit Zeitstempel.
  • Führen Sie niemals einen vollständigen Scan oder eine Operation mit mehr als O (Log N) auf einem solchen Volume durch. Wenn Sie mehr als O (Log N) benötigen, verlagern Sie diese Operationen in Map-Reduce-Algorithmen.

Trainieren

  • Verbringen Sie keine Zeit damit, Betriebssystem-Images zu erstellen oder Server auf physischen Maschinen zu installieren. Verwenden Sie Cloud-basierte Anbieter für schnelles Prototyping. Ich habe mit Amazon EC2 gearbeitet und kann es aufgrund seiner Einfachheit, Zuverlässigkeit und Geschwindigkeit des Prototyping nur empfehlen.
  • Windows-Computer sind in der Regel während des Startvorgangs langsamer und beanspruchen erheblich mehr Ressourcen, wenn sie sich im Leerlauf befinden. Erwägen Sie die Verwendung eines Unix-basierten Betriebssystems. Ich persönlich fand, dass Ubuntu Server ein zuverlässiges Betriebssystem ist, aber außerdem gibt es bei askubuntu eine ziemlich gute Community
  • Denken Sie an die Vernetzung, Knoten sollten idealerweise nahe beieinander liegen, um schnelles Klatschen und Metadatenaustausch zu ermöglichen.
  • Gehen Sie nicht in Extremfälle: wirklich breite Spaltenzeilen oder außergewöhnlich lange Spaltenfamilien (Tabellen). Die beste Leistung wird an den normalen Grenzen erzielt. Wenn db so viele N Zeilen unterstützt, bedeutet dies nicht, dass die Leistung gut ist.
  • Unsere Suche dauert ungefähr 3 bis 5 Sekunden. Vieles liegt an den Zwischenknoten zwischen der Benutzeroberfläche und der Datenbank. Überlegen Sie, wie Sie Anforderungen näher an die Datenbank bringen.
  • Verwenden Sie einen Netzwerklastenausgleich. Wählen Sie eine etablierte. Wir verwenden HAProxy, das einfach, aber absolut schnell ist. Hatte noch nie Probleme damit.
  • Bevorzugen Sie die Einfachheit gegenüber komplexen Lösungen.
  • Suchen Sie nach kostenlosen Open-Source-Lösungen, es sei denn, Sie verfügen über das Budget eines Unternehmens. Wenn Sie mehr als mehrere Server einsetzen, können die Kosten für die Infrastruktur in die Höhe schnellen.

Ich arbeite nicht für Amazon und habe keine Beziehung zu HAProxy- und Ubuntu-Teams. Dies ist eine persönliche Meinung und keine Werbung.


5
Ich bin mir ziemlich sicher, dass eine O (1) -Suche unmöglich ist, abgesehen von extrem unbedeutenden / nutzlosen Fällen.
Fitzsimmons

2
Bitte nehmen Sie keine Beleidigung, aber teilen Sie das Google mit. O (1) -Suche ist auf PB-Skala unter sorgfältiger Planung möglich.
oleksii

9
@oleksii Milliarden Dollar Google-Budgets sind kein vernünftiger Vergleich zu ziehen.
Mark Storey-Smith

4
Ich kann die 3 vorherigen Kommentare mitO(1) search <=> unbounded storage space <=> unlimited supply of cash
ypercubeᵀᴹ verbinden.

3
O (1) Die Suche nach einem einzelnen Datensatz kann mit einer linearen Hash-Tabelle durchgeführt werden. . Auf diese Weise können Sie jedoch nicht effizient nach Bereichen suchen. Dazu benötigen Sie eine Variante einer BTree-Struktur, die für ein einzelnes Element O (log n) ist.
ConcernedOfTunbridgeWells

41

Wenn ich dies in SQL Server einfügen würde, würde ich eine Tabelle vorschlagen, die ungefähr so ​​aussieht:

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 */
);

Dies ergibt einen geschätzten Gesamtspeicherbedarf für die einzelne Tabelle, ohne weitere Indizes von 5,5 TB für 43,2 Beeellion-Datensätze (Ihre angegebene Anforderung). Dies berechnet sich aus 130 Bytes für die Daten selbst plus 7 Bytes pro Overhead-Zeile plus 96 Bytes pro Overhead-Seite. SQL Server speichert Daten auf 8 KB-Seiten, wobei 59 Zeilen pro Seite zulässig sind. Dies entspricht 732.203.390 Seiten für einen einzelnen Datenmonat.

SQL Server schreibt gerne in 8-Seiten-Blöcken (64 KB) auf die Festplatte, was 472 Zeilen pro physischer E / A entspricht. Da jede Sekunde 16.203 Flow-Datensätze generiert werden, benötigen Sie eine minimale E / A-Rate von 34 IOps, die jede Sekunde garantiert wird. Obwohl dies an sich keine große Menge ist, müssen andere E / A-Vorgänge im System (SQL Server und andere) diese erforderliche IOps-Rate niemals beeinträchtigen. Daher müssten Sie ein System entwerfen, das mindestens eine Größenordnung mehr IOps oder 340 nachhaltige IOps unterstützt. Ich würde eher schätzen, dass Sie 2 Größenordnungen nachhaltigere IOps benötigen, um den Durchsatz zu gewährleisten.

Sie werden feststellen, dass ich die IP-Adressen nicht in ihrer Punkt-Dezimal-Form speichere. Dies spart viel Speicherplatz (7 Byte pro Adresse) und macht das Indizieren, Abrufen, Sortieren und Vergleichen von IP-Adressen weitaus effizienter. Der Nachteil hierbei ist, dass Sie die IP-Adressen mit gepunkteten Dezimalstellen vor dem Speichern in 8-Byte-Ganzzahlen und zur Anzeige wieder in IP-Adressen mit gepunkteten Dezimalstellen konvertieren müssen. Der dazu erforderliche Code ist trivial, jedoch erhöht sich durch die Zeilenrate der Verarbeitungsaufwand für jede zu verarbeitende Ablaufzeile erheblich. Möglicherweise möchten Sie diesen Konvertierungsprozess auf einem physisch anderen Computer als SQL Server ausführen.

Das Erörtern der von Ihnen benötigten Indizes ist eine völlig separate Angelegenheit, da Sie keine spezifischen Anforderungen aufgeführt haben. Das Design dieser Tabelle speichert Flusszeilen in der physischen Reihenfolge, in der sie von SQL Server empfangen werden. Das tcp_traffic_idFeld ist für jeden Datensatz eindeutig und ermöglicht das Sortieren der Zeilen nach der Reihenfolge, in der sie aufgezeichnet wurden (in diesem Fall höchstwahrscheinlich eins zu eins) zum Zeitpunkt des Durchflussereignisses).


4
Ich würde wahrscheinlich binary(4)bzw. binary(16)verwenden. 4 Bytes / Zeile ergeben eine Menge Speicher, multipliziert mit 1.000.000.000.000.
Jon Seigel

2
Und Portnummern haben einen Bereich von 0-65535, sodass Sie diesen verwenden können, SMALLINTaber auch dort muss eine Konvertierungsroutine vorhanden sein.
Ypercubeᵀᴹ

7
@ MrTelly Ich bin anderer Meinung. Dies in SQL Server zu tun, ist nur dann teuer, wenn Sie HA oder umfangreiches Failover-Material benötigen. Für einen soliden Datenspeicher, mit dem man sehr leicht leben kann, ist SQL Server eine großartige Lösung. Alle Systeme werden sehr teuer (und kompliziert), wenn HA benötigt wird.
Samsmith

2
IMO, SQL Server kann die Daten definitiv speichern . Ich bin mir immer noch nicht sicher, ob es die richtige Lösung ist, um den Analyseteil des Projekts zu lösen , hauptsächlich, weil ich mit den anderen betrachteten Systemen nicht vertraut genug bin.
Jon Seigel

3
@MrTelly Es gibt zwei Ausgaben: a) Festplattenspeicher (für 5 bis 8 TB, abhängig vom von den Indizes verwendeten Speicherplatz) b) RAM (zur Unterstützung von Abfragen, Index-Caching). Dies monolithisch zu tun, würde normalerweise mit einem großen RAID10-Array oder SAN erfolgen. Beachten Sie jedoch, dass das Sharding durchaus möglich ist und Sie die Logik auf Anwendungsebene verwenden können, um die Arbeitslast auf mehrere SQL Server zu verteilen. Auf diese Weise können Sie billige Server mit jeweils 0,5 bis 2 TB und möglicherweise sogar die kostenlose SQL Server-Edition verwenden. (Beachten Sie, dass Sharding ein allgemeines Konzept ist, häufig auf App-Ebene durchgeführt wird und für jede Persistenzmethode gilt.)
samsmith

5

Ich würde HBase empfehlen . Sie können alle Rohdaten in einer oder mehreren HBase-Tabellen speichern, je nachdem, was Sie abfragen müssen. HBase kann mit großen Datenmengen umgehen und führt eine automatische Splittung durch.

Wenn Sie Zeilenschlüssel gut entwerfen, können Sie außerdem extrem schnelle, sogar O (1) -Anfragen erhalten. Beachten Sie, dass das Abrufen großer Datenmengen immer noch langsam ist, da es sich beim Abrufen von Daten um eine O (n) -Operation handelt.

Da Sie für jedes Feld eine Abfrage durchführen möchten, würde ich empfehlen, für jedes Feld eine eigene Tabelle zu erstellen. Beispiel für die src_address-Daten: Eine Tabelle sieht folgendermaßen aus:

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

Wenn Sie also alle Daten in 1.2.3.4 ab dem 27. März, 00:00 Uhr, bis zum 27. März, 00:01 Uhr, abfragen möchten, können Sie einen Bereichsscan mit den angegebenen Start- und Stoppzeilen durchführen.

Meiner Meinung nach ist der Zeilenschlüsselentwurf der wichtigste Teil der Verwendung von HBase. Wenn Sie ihn gut entwerfen, können Sie schnelle Abfragen durchführen UND große Datenmengen speichern.


3

Sagte das :

... wir sind nicht dagegen, proprietäre Lösungen für dieses Projekt zu suchen

Ich schlage vor, IBM Informix-Datenbank + TimeSeries- Datablade zu berücksichtigen. Im Gegensatz zu dem, was manche Leute sagen, lebt Informix und läuft sehr gut. Die letzte Version wurde letzten Monat veröffentlicht (März / 2013, Version 12.10).

TimeSeries ist wie ein "Plugin" (kostenlos), das in der Lage ist, mit Situationen wie Ihrer umzugehen.
Und Sie können es in der Produktion mit der kostenlosen Version der Informix-Datenbank ( Edition Innovator-C ) verwenden. (Natürlich nur, um die technischen Teile zu bewerten, da die kostenlose Version viele begrenzte Ressourcen hat)

Hier können Sie ein Benchmark-PDF überprüfen , das als Referenz verwendet werden kann. Hier zwei Präsentationen mit mehr technischen Beispielen: Dummies Guide und andere Tipps

Ich habe keine persönlichen Erfahrungen mit TimeSeries , daher kann ich nicht zustimmen, dass dies "die Lösung" ist, sondern nur ein Vorschlag zur Bewertung.


2

Ich schließe mich der Empfehlung an, sich Informix TimeSeries anzuschauen. IBM Literatur behauptet, dass TimeSeries diese Art von Informationen in einem Fünftel des Speicherplatzes speichern und 5-mal so schnell ausführen kann wie herkömmliche relationale Tabellen.

Weitere Vorteile wären die virtuelle Tabellenschnittstelle, mit der TimeSeries-Daten für den Endbenutzer wie herkömmliche relationale Tabellen angezeigt werden können (was die Anwendungsentwicklung vereinfacht und gleichzeitig die Vorteile von TimeSeries nutzt), die einfache Hochverfügbarkeit mit HDR-Knoten, die jetzt TimeSeries-Daten in Version 12.1 unterstützen, und die Integration von TimeSeries-Daten in den Informix Warehouse Accelerator, mit dem sich komplizierte Data Warehouse-Berichte beschleunigen lassen und eine TimeSeries-Lösung in Informix mit den kostenlosen Informix Developer- oder Innovator-C-Editionen prototypisieren lässt.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.