5

Ich erstelle ein Metrik-Berichtssystem für eine Instanzflotte mit mehr als 100.000 Front-End-Instanzen. Für jede Anfrage hat jede einzelne Instanz eine Antwortzeit. Und was ich brauche, ist die Verteilung der Reaktionszeit aller Arten von Anfragen über die gesamte Flotte. Zum Beispiel die [Perzentil 50, Perzentil 90, Perzentil 99, Perzentil99.9 ...] von [requestType1, requestType2 ... requestType1000].Wie berechnet man die Verteilung (Histogramm) großer Datenmengen in einem verteilten System?

Jede Instanz wird die Antwortzeit im Inneren sammeln. Eine Minute lang sammelt eine Instanz im Speicher die Listen der Antwortzeit aller Arten von Anfragetypen. Zum Beispiel requestType1 - [1, 2, 3, 4, 1, 2], requestType2 - [2, 2, 3, 2, 1] ...... Also was ich tun muss, ist diese Daten zu verarbeiten und zu produzieren das Endergebnis.

Ich habe viele Designs ausprobiert, meine Hauptprobleme sind die riesige Größe der Datenpunkte, die ich von jedem einzelnen requestType gesammelt habe, und die Kosten der Kommunikation zwischen Instanzen. Ich werde mein derzeitiges Design unten erklären, aber ich möchte auch wissen, ob es bessere Designs gibt oder einige ausgefallene Algorithmen Histogramme zusammenfassen können?

Derzeit ist die vielversprechendste: Jede Front-End-Instanz sendet ihre Daten an eine zufällige Instanz einer Midlayer-Instance-Flotte. In dieser Mid-Layer-Flotte aggregiert jede Instanz alle Datenpunkte, die sie über einen kurzen Zeitraum erhält, z. 5 Sekunden. (Es hat nicht genug Speicher für eine längere Zeit). Anschließend verteilt die Midlayer-Instanz die aggregierten Daten nach Hash-Werten von requestTypes an Back-End-Instanzen. Dies bedeutet, dass alle Midlayer-Instanzen die Datenpunkte derselben requestTypes an dieselbe Back-End-Instanz senden. Dann kann ich in der Backend-Instanz den Histogrammcontainer eines Drittanbieters (CodaHale's Histogramm oder HdrHistogramm) verwenden, um P50, P90, P99 von eingehenden Datenpunkten zu berechnen ... Der Grund, warum ich die Midlayer-Instanzflotte brauche, ist das Senden von Daten von End-Instanzen sind teuer, daher möchte ich, dass alle Daten gleichzeitig gesendet werden, aber nicht 100 Aufrufe an 100 verschiedene Back-End-Instanzen senden.

Das Hauptproblem, das ich an dieses Design denken kann, ist die relativ hohe Komplexität, und wenn eine Back-Instanz ausfällt, kann ich alle Daten einiger requestTypes verlieren. Also für die System-Design-Teil, hat jeder ein paar bessere Ideen?

Die andere Weise, die ich denke, ist, einen fantastischen Algorithmus zu finden, um vorhandene Histogramme zu aggregieren. Das Design oben, die Daten, die ich bekomme, wird 100% genau sein. Aber tatsächlich kann ich einige Fehler tolerieren. Zum Beispiel in CodaHale's Histogramm und HdrHistogramm, ich bin mir sicher, dass sie nicht alle Datenpunkte speichern, sondern einige fortgeschrittene mathematische Algorithmen anwenden, um ein relativ hochpräzises Ergebnis mit sehr niedrigen Kosten zu erhalten. Und ich kann die Histogramm-Bibliothek in Front-End- oder Midlayer-Instanzen verwenden. Aber die Probleme sind, obwohl ich die [P50, P90, P99 ...] jeder Frontend-Instanz oder Midlayer-Instanz zu niedrigen Kosten bekommen kann, ich konnte keine Möglichkeit finden, sie zu aggregieren. Da verschiedene Front-End-Instanzen unterschiedliche Arten von Anforderungen verarbeiten können und die Verteilung von Anforderungen an Front-End-Instanzen unbekannt ist, berechnen Sie einfach den Durchschnittswert von ALL P50, P90, P99, der viele Ungenauigkeiten aufweist. Hat also jemand eine Idee, wie kann ich mehrere CodaHale Histogramme oder HdrHistogramme zusammenfassen? Oder können Algorithmen helfen, Histogramme zu einem zusammenzufassen?

============================================= ========================

Ich habe letzte Nacht eine neue Idee. Da P50 und P90 den "Durchschnitt" aller Daten messen, denke ich, dass einfach gewichteter Durchschnitt auf allen P50 angewendet wird und P90, berechnet in jeder mittleren Schicht, sollte gut genug sein. Aber P99, P99.9 und P99.99 messen diese äußeren Daten, so dass ein Durchschnitt von P99 der Teilmenge möglicherweise nicht genau ist.

Wenn jedoch angenommen wird, dass die Daten in der Midlayer-Instanz relativ zufällig verteilt sind, kann ich in jeder Midlayer-Instanz die obersten 5% der Datenpunkte erhalten und sie an das Back-End senden. Die 5% aller mittleren Datenpunkte zusammen sind 5% der gesamten Datenpunkte. Und ich habe mehr Zuversicht, dass der P80 dieser 5% Daten nahe bei P99 der Gesamtdaten liegt, P98 dieser 5% Daten liegt nahe bei P99.9 der Gesamtdaten und P99.8 von 5% Daten liegt nahe bei P99 .99 der Gesamtdaten.

Ich hoffe auf diese Weise kann ich nur 5% der Gesamtdaten übertragen, aber eine hohe Genauigkeit Ergebnis erhalten. Was denkst du über diesen Weg?

+0

Sie feststellen, dass 'Für jede Anfrage wird jede einzelne Instanz eine Antwort time.' haben, die wie jede Instanz klingt für mich wird jede einzelne Anforderung verarbeiten Sie übertragen, aber später sagen Sie dann: 'Weil verschiedene Front-End-Instanzen unterschiedliche Arten von Anfragen bearbeiten können und die Verteilung von Anfragen an Front-End-Instanzen unbekannt ist [...], was etwas anderes bedeutet. Können Sie etwas mehr erklären, wie die Anforderungsbehandlung funktioniert? –

+1

Erhalten Sie tatsächlich die Antwortzeiten als ganze Zahlen (oder runden Sie ganze Zahlen ab)? Dies würde bedeuten, dass (z. B. das Zählen von Sort oder etwas Ähnlichem) und das Kodieren Ihrer Daten mit RLE die Kommunikation ein wenig beschleunigen sollten. –

+0

Wenn eine Anfrage an die Front-End-Flotte gestellt wird, wählt das System eine Instanz aus, um die Anfrage zu bearbeiten. Es ist eine Blackbox, daher weiß ich nicht, welche Instanz die Anfrage bearbeiten wird. Aber es gibt sicher nur eine einzige Instanz, die eine Anfrage bearbeitet. –

Antwort

1

Systemdesign:

Wenn Anrufe teuer sind dann vielleicht könnten Sie die Daten streamen? Ich sehe keine wirklichen Vorteile dieser Mid-Tier in Ihrer Beschreibung - warum Frontend-> mittlere Anrufkosten sind niedriger als Frontend-> Backend?

Wenn Sie Datenverlust betroffen sind, haben Sie zwei Möglichkeiten:

  • Ereignisse an mehrere Knoten senden. Sie müssen jedoch bei der Verarbeitung Doppelarbeit vermeiden.
  • schreibt alles auf ein beständiges Protokoll (Kafka konnte die Arbeit hier tun)

Alles auf dem Volumen von Ereignissen abhängig (1/min/Frontend oder 10k/s/Frontend) und die Entfernung zwischen Frontend und das Backend (dasselbe Datencenter oder mobile Geräte -> Datencenter?).

Wenn es dasselbe Datencenter ist, können Sie mit dem Backend über persistentes Protokoll kommunizieren - dies löst das Problem des Datenverlustes. Wenn es viele Ereignisse könnte man sie auf den Frontends aggregieren und schieben Aggregate Downstream

Aggregation:

Es gibt verschiedene Algorithmen, zum Beispiel q-Digest, t-Digest. Siehe Quantiles over Data Streams: An Experimental Study

Es ist auch erwähnenswert, dass HdrHistograms can be combined

Verwandte Themen