2017-02-06 1 views
0

Ich versuche, einen Zeitreihendienst basierend auf Cassandra zu entwerfen, der einige Protokollinformationen verfolgen wird. Die Datenbank wird ein relativ hohes Volumen an Schreibvorgängen (mit ~ 500 mil Einsätzen/Tag) und weniger häufigen, aber großen Lesevorgängen (denken Sie an einen Tag Daten oder einen Monat Daten) sehen.Cassandra timeseries modellieren

Das vereinfachte Datenmodell von einem Protokolleintrag sieht wie folgt aus (in Wirklichkeit hat es 50 oder so Spalten):

log_datetime date 
log_some_field text 
log_some_other_field text 

Die meisten Anfragen lesen um die Auswahl von Daten aus einem bestimmten Datumsbereich drehen wird, immer bestellt absteigend Nach Datum. (z.B. SELECT * FROM logs WHERE log_datetime >= 2012-01-01 and log_datetime <= 2012-02-01 ORDER BY log_datetime DESC). Dies wird normalerweise viel Zeit in Anspruch nehmen, deshalb möchte ich so viel wie möglich dafür optimieren.

Wie Bestellung und die Filterung nach Datum sind die wichtigsten Eigenschaften, solange schreibt nicht zu schrecklich sind, die erste Idee war so etwas wie dieses zu definieren (wo log_day der Tag des Jahres):

CREATE TABLE logs(
    log_day tinyint 
    log_datetime timeuuid 
    log_some_field text 
    log_some_other_field text 
    PRIMARY KEY (log_day, log_datetime) 
    WITH CLUSTERING ORDER BY (log_datetime DESC) 
) 

Es ist mein Verständnis, dass dies den Abruf so gut wie möglich macht, da die Daten geordnet sind und eine einzelne Partition benötigt wird, um einen Tag abzurufen (ich kann in dem Client die Fälle behandeln, in denen mehrere Tage ausgewählt sind). Dies würde jedoch dazu führen, dass Schreibvorgänge auf einen einzelnen Server übertragen werden, was die Schreibleistung erheblich beeinträchtigen würde. Die andere Option ist die Auswahl eines zufälligen Sets, das als Partitionsschlüssel verwendet wird und vom Client auf Round-Robin verteilt wird, was die Schreibvorgänge schneller und skalierbarer macht, aber zu schlechterer Leseperformance führt, insbesondere wenn wir neu sortieren müssen die Daten. Die meisten Beispiele, die ich gesehen habe, haben normalerweise natürliche Partitionsschlüssel in der Datenmenge wie eine user_id oder eine post_id, was nicht mein Fall ist.

Hat jemand hier einen ähnlichen Anwendungsfall? Wenn ja, welche Kompromisse haben Sie gemacht, um eine ordentliche Leistung zu erzielen? Kennen Sie Datenbanken, die in solchen Anwendungsfällen besser funktionieren?

Antwort

1

Wie Sie feststellen, bedeutet die Verwendung von Tag als Partitionsschlüssel, dass Schreibvorgänge für einen ganzen Tag an einen einzelnen primären Knoten gesendet werden. Die Daten werden in Cassandra basierend auf dem Replikationsfaktor, typischerweise 3, repliziert. Somit würden an jeden beliebigen Tag drei Knoten geschrieben.

Wenn das Datenvolumen niedrig war, könnte dies akzeptabel sein. Im Allgemeinen ist es nicht und man würde irgendeine Art von Zeitfenster verwenden, wie z. B. 5- oder 10-Minuten-Intervalle, die in der Anwendung berechnet werden.

CREATE TABLE logs(
    log_day tinyint 
    timebucket tinyint 
    log_datetime timeuuid 
    log_some_field text 
    log_some_other_field text 
    PRIMARY KEY ((log_day, timebucket) log_datetime) 
    WITH CLUSTERING ORDER BY (log_datetime DESC) 
) 

Die Auswahl eines geeigneten Zeitintervalls für den Bucket hängt mit Ihrem erwarteten Datenvolumen zusammen. Mit 500 Millionen Schreibvorgängen pro Tag sind das etwa 6.000 pro Sekunde. Ihre Zeit-Buckets könnten sich zu jeder vollen Stunde einklappen lassen, so dass Sie nur 6 (10 Minuten) oder einen ganzen Tag mit 144 einzigartigen Buckets haben. Wenn Sie Ergebnisse lesen, muss Ihre Anwendung alle Buckets für einen bestimmten Tag lesen und die Ergebnisse zusammenführen (aber nicht sortieren).

In einer Anwendung vom Typ syslog kann die Verwendung von Schweregrad plus Tag im Partitionsschlüssel dazu beitragen, die Last über den Cluster mit einem natürlichen Schlüssel zu verteilen. Es wäre immer noch klumpig, weil die Anzahl der Info-Nachrichten viel besser ist als Warnungen, Fehler oder fatale Nachrichten.

+0

Mit dem Zeitfenster würden wir immer noch eine ungleichmäßige Verteilung sehen oder fehlt mir etwas (z. B. würde ein Server alle Anfragen für 5 Minuten erhalten)? Kann ein einzelner Node von Cassandra ~ 10k req/Sekunde verarbeiten oder wäre es besser, nur Round Robin für die Client-Anwendung zu verwenden? – woland

+0

Ja, es würde Daten für die Dauer des Zeitbereichs in den primären Knoten schreiben, z. B. 5 Minuten. Sie können dies so klein wie Sie möchten.Alternativ können Sie mit minutes% 10 10 Buckets erstellen, die jede Minute zwischen Knoten rotiert werden. Ihre Hardware wird wirklich bestimmen, ob 10k/sec nachhaltiger Durchsatz ist oder nicht. – Bradski