2009-04-12 7 views
8

Die Firma, für die ich arbeite, erstellt Anwendungen für die Blackberry-Plattform.Der beste Weg, ein skalierbares Hits/Analytics-System zu entwickeln?

Wir haben an einem proprietären "Analysesystem" gearbeitet, das es uns ermöglicht, Code in unsere Anwendungen einzubetten und die Anwendungen jedes Mal, wenn sie laufen, Statistiken auf unseren zentralen Servern zu melden. Derzeit funktioniert das System einwandfrei. Aber es ist nur in der Beta mit 100-200 Treffern pro Stunde. Die "Treffer" werden problemlos an die Server gesendet. Wir haben eine sehr solide API entwickelt, um die Akzeptanz und Speicherung der Treffer (in einer MySQL DB) zu handhaben. Wir haben die Last getestet und wir sollten in der Lage sein, Hunderttausende von Treffern pro Stunde ohne Probleme zu bewältigen. Das ist nicht wirklich ein Problem.

Das Problem zeigt die Statistik. Wir haben ein Display ähnlich Mint's (haveamint.com) gebaut, es zeigt die Hits über jede Stunde, die letzten Tage, Monate, Wochen, Jahre ... usw. Die erste Version führte gerade Abfragen durch, indem sie Daten aus der Treffertabelle extrahierte und sie im Hintergrund interpretierte. Das hat nicht lange funktioniert. Unsere aktuelle Lösung ist, dass die Treffer für die Verarbeitung "in die Warteschlange gestellt" werden und wir alle 5 Minuten einen Cron bekommen, der die Treffer nimmt und sie in "Caches" für jede Stunde, jeden Tag, jede Woche, jeden Monats, jedes Jahres sortiert. Dies funktioniert erstaunlich und es ist unglaublich skalierbar; Es funktioniert jedoch nur für 1 Zeitzone. Da das gesamte Unternehmen darauf zugreifen kann, haben wir es mit einigen hundert Benutzern in verschiedenen Zeitzonen zu tun. Was ich in San Jose als "Heute" definiere, ist VIEL anders als das, was mein Kollege in London als Heute definiert. Da die aktuelle Lösung nur in einer Zeitzone zwischengespeichert wird, ist dies ein Albtraum für jeden, der die Daten außerhalb unserer Zeitzone überprüft.

Unser aktueller Plan, dies zu beheben, ist das Erstellen von Caches für jede Zeitzone (40 insgesamt); das würde aber bedeuten, dass wir die Datenmenge mit 40 multiplizieren ... das ist schrecklich für mich, und da die Caches sehr groß sein können, ist es einfach eine schlechte Idee zu multiplizieren; Wenn wir die Warteschlange bearbeiten, wird es viel mehr CPU-Zeit benötigen, um sie in 40 verschiedene Caches zu laden.

Jeder andere hat eine bessere Idee, wie man dieses Problem lösen kann?

(Sorry für eine so lange question..it ist nicht ganz einfach zu erklären. Dank all!)

+0

So spezifisch wie Ihre Frage ist, ich entwerfe tatsächlich etwas sehr ähnliches und würde hier für die Eingabe kommen. +1 –

+0

Es wäre sehr interessant zu sehen, Ihre Hit-Handling/Speichern API :) – Jacco

Antwort

4

Die Lösung, die Sie vorschlagen, hat zu viel Redundanz. Ich würde vorschlagen, dass Sie die Daten in mindestens 30-Minuten-Buckets anstatt stündlich speichern und die Zeitzone auf UTC normalisieren.

Mit 30-Minuten-Buckets, wenn ein Benutzer stündliche Daten für 1 - 2PM von -4.5 UTC anfordert, können Sie Daten von 17.30 bis 18.30 Uhr von Ihrem System abrufen und dies anzeigen. Wenn Sie Daten in einstündigen Schritten speichern, können Sie Anforderungen an Benutzer in Zeitzonen mit N + 0,5-Stunden-Differenzen nicht bearbeiten.

Für tägliche Nummern müssten Sie 48 halbe Stunden Slots aggregieren. Die zu wählenden Slots werden von der Zeitzone des Benutzers bestimmt.

Es wird interessant, wenn Sie zu jährlichen Daten kommen, weil Sie am Ende 17.520 Halbstunden-Buckets aggregieren müssen. Um diese Berechnung zu vereinfachen, würde ich vorschlagen, dass Sie die voraggregierten Jahresdaten pro UTC-Zeit erhalten und die aggregierten Daten für die ersten 4,5 Stunden des Jahres abziehen und aggregierte Daten für die ersten 4,5 Stunden des nächsten Jahres hinzufügen. Dies wird das ganze Jahr um 4,5 Stunden verschieben und die Arbeit ist nicht so viel. Von hier aus können Sie das System weiter optimieren.

EDIT: Es stellt sich heraus, dass Kathmandu +5,45 GMT ist, so dass Sie die Daten in 15-Minuten-Buckets anstelle von 30-Minuten-Buckets speichern müssten.

BEARBEITEN 2: Eine weitere einfache Verbesserung besteht in der jährlichen Aggregation, so dass Sie nicht jedes Mal 17.520 Buckets hinzufügen müssen, ohne ein Aggregat pro Land zu benötigen. Aggregieren Sie die jährlichen Daten vom 02.01. - 30.12. Da der maximale Zeitzonenunterschied zwischen zwei beliebigen Ländern 23 Stunden beträgt, können Sie also die jährlichen Daten (02.01. - 30.12.) Nehmen und davor und danach ein paar Buckets hinzufügen wie angemessen. Für eine Zeitzone von -5 UTC würden Sie beispielsweise alle Buckets am 1. Januar nach 0500, alle Buckets am 31. Dezember und am 01. Januar des folgenden Jahres bis 0500 Stunden hinzufügen.

+1

+1 für die Diskussion über Eimer Größe – lpfavreau

+1

Dies scheint die beste Option. 15-Minuten-Buckets sind vielleicht nicht wert, wenn man bedenkt, dass nur eine sehr kleine Anzahl von Menschen diese Zeitzonen belegen wird. –

2

Wenn Software entwerfen, die mehrere Zeitzonen berührt, würde ich sagen immer in Ihrem Datum/Uhrzeit speichern UTC mit ein anderes Feld für die ursprüngliche Zeitzone und eine Funktion, die sich die Zeit nimmt und sie in und aus UTC/Zeitzone konvertiert. Sie sparen sich eine Menge Ärger, um mit den verschiedenen Fällen von Tageswechsel, Sommerzeit, Leuten, die Statistiken aus einem Land von der anderen Seite der Erde betrachten, umzugehen ...

In Ihrem Fall Es sollte helfen, die Caches in UTC zu haben und nur die Anfragen anzupassen, die in UTC konvertiert werden sollen. Speichern Sie keine Statistik als "heute", speichern Sie sie stundenlang 00: 00: 00UTC bis 23: 59: 59UTC und wenn jemand nach den Statistiken für heute in New York fragt, machen Sie die Konvertierung.

+0

Ich sehe keinen Grund für die Verbesserung hier. Es geht wirklich nicht darum, wie Sie tägliche Daten für New York bekommen würden, weil Sie den Tag nicht einfach 5 Stunden verschieben können. Sie benötigen die Daten der letzten 5 Stunden und Sie müssen die letzten 5 Stunden subtrahieren, wie ich es in meiner Lösung vorgeschlagen habe. – aleemb

+0

Ich habe in dieser Lösung nie über Eimergröße gesprochen. Ich sage nur, dass ich die Buckets in UTC von 00:00 bis 23:59 statt in Ortszeit machen soll. Da nicht genügend Details darüber vorliegen, welche Statistiken in der Benutzeroberfläche vorgeschlagen werden, ist es nicht möglich, eine definitive Bucket-Größe vorzuschlagen. – lpfavreau

+0

@aleemb: Es gibt keinen Grund für einen Downvote, da Sie genau dasselbe vorschlagen, aber die Diskussion über die Größe der Buckets erweitert hat, was großartig ist. – lpfavreau

0

Soweit ich sehen kann, suchen Sie hier den Speicherbereich eines Data-Warehouse-Systems (Ihre Berichte wären das Front-End).

Eigentlich ist die Art, wie kommerzielle Systeme es tun, der Cache, den Sie beschrieben: Preaggregate Ihre Tabellen und erstellen Sie Caches von ihnen. Die einzige Möglichkeit, Ihre Abfragen zu beschleunigen, besteht darin, das Datenbanksystem dazu zu bringen, weniger für sie zu tun. Dies bedeutet weniger Daten, was wiederum weniger Zeit für die Iteration der Daten oder weniger Daten in den Indizes bedeutet.

Das heißt, ich würde entweder die "40 Cache-Lösung" vorschlagen (gibt es wirklich mehr als 24 Zeitzonen). Sie sollten die Sortierwarteschlange trivialisieren können, indem Sie Kopien der Daten erstellen.

Eine andere Möglichkeit wäre, die Stundengranularität zwischenzuspeichern und dann die Stunden zu Tagen zu aggregieren (oder 30 Minuten, wenn Ihre Zeitzonen dies erfordern). Dies bedeutet, dass Sie mit einer feineren Granularität als Ihrem täglichen Cache zwischenspeichern, jedoch mit einer gröberen Granularität als die ursprünglichen Daten.