Zurück zum Blog

Stabilität bei großskaliger Datenerfassung: Probleme, die erst beim Hochskalieren sichtbar werden

Eine Erfassung kann bei zehn Zielen stabil laufen und bei Tausenden einbrechen. Fehlerklassifizierung und Deduplizierung, Rate-Limits und Parallelität, Wiederaufnahme, Ausfälle von Netzwerk-Ausgängen, Konsistenzprüfungen und wenige zentrale Metriken werden erst im großen Maßstab kritisch.

Ein Erfassungsskript kann bei zehn Zielen problemlos laufen und bei Tausenden plötzlich an Erfolgsquote verlieren. Man ergänzt Wiederholungen, wechselt Proxys, passt die Parallelität an, doch die Probleme kehren zurück. Bei genauerer Analyse liegt die Ursache oft nicht in der Parsing-Logik, sondern in fehlenden Engineering-Schichten. Im kleinen Maßstab treten diese Themen häufig gar nicht auf.

Fehler zuerst klassifizieren, damit Wiederholungen sinnvoll sind

Fehler gehören zur Datenerfassung dazu. Entscheidend ist ihre Einordnung: Netzwerkschwankungen und Verbindungsabbrüche können sofort erneut versucht werden; bei temporären Rate-Limits sollte nach einem Backoff erneut versucht werden; führt eine geänderte Seitenstruktur zu leeren Parsing-Ergebnissen, helfen auch zehntausend Wiederholungen nicht – der Fall muss protokolliert und gemeldet werden; existiert das Ziel gar nicht, kann die Aufgabe als abgeschlossen markiert werden; lässt sich eine Umgebung oder ein Netzwerk-Ausgang nicht starten, wird gewechselt und erneut versucht.

Alles pauschal erneut zu versuchen, ist einer der häufigsten Fehler. So werden Probleme, die menschliches Eingreifen brauchen, in Schleifen versteckt, während Kontingente und Ausgänge unnötig verbraucht werden. Auch Backoff ist wichtig: Die Abstände zwischen Wiederholungen sollten wachsen, sonst schlägt eine ganze Aufgabenserie im selben Zeitfenster erneut auf und verschärft das Rate-Limiting.

Wiederholungen führen direkt zum Thema Deduplizierung. Eine Aufgabe kann durch Retries mehrfach ausgeführt werden, deshalb braucht jede Aufgabe eine stabile eindeutige Kennung – etwa den Wert nach URL-Normalisierung – und Schreibvorgänge sollten anhand dieser Kennung idempotent sein. Sonst erzeugen mehr Wiederholungen nur mehr fehlerhafte oder doppelte Daten.

Rate-Limiting und Parallelität sind zwei verschiedene Dinge

Mehr Parallelität bedeutet nicht automatisch mehr Durchsatz. Gleichzeitig wirken drei Grenzen: wie viel die Zielseite verträgt, bevor Rate-Limiting den Gesamtdurchsatz senkt, Arbeitsspeicher und CPU des lokalen Systems sowie die Frage, ob eine einzelne Umgebung oder Sitzung mehrere Aufgaben gleichzeitig ausführen kann.

Ein stabiler Ansatz startet mit niedriger Parallelität und erhöht die Last schrittweise. Erfolgsquote und Antwortzeit werden gemeinsam betrachtet, um den Punkt zu finden, an dem sich die Werte deutlich verschlechtern. Rate-Limiting ist davon getrennt: Es steuert das Zugriffstempo auf dasselbe Ziel und ist nicht identisch mit der globalen Parallelität. Verteilt sich eine Aufgabenserie auf mehrere Websites, braucht jede Website ihre eigene Taktung.

Wiederaufnahme braucht persistenten Status

Bei Aufgaben, die mehrere Stunden laufen, sind Unterbrechungen normal; ein kompletter Neustart ist oft zu teuer. Voraussetzung ist, den Status dauerhaft zu speichern: ausstehend, in Bearbeitung, abgeschlossen sowie Anzahl der Wiederholungen, nächster zulässiger Ausführungszeitpunkt und Fehlertyp. Beim Prozessstart wird die Warteschlange aus dem Speicher geladen, statt sie aus flüchtigem Arbeitsspeicher neu aufzubauen.

Eine Warteschlange nur im Arbeitsspeicher zu führen, ist eine typische Lösung, die zunächst funktioniert. Stirbt der Prozess, gehen alle wartenden Aufgaben verloren und die Zahlen lassen sich nicht mehr abgleichen.

Proxy- und Ausgangsausfälle getrennt behandeln

Dass ein Ausgang vom Ziel blockiert wird, ein Proxy ausfällt oder ein regionaler Knoten driftet, passiert im großen Maßstab fortlaufend. Das sind keine seltenen Ausnahmen, sondern Normalfälle. Ausgänge sollten als austauschbare Ressourcen behandelt werden: Bei einem Fehler wird zuerst unterschieden, ob das Ziel drosselt oder der Ausgang nicht verfügbar ist; im ersten Fall Backoff, im zweiten Ausgang wechseln und erneut versuchen. Zusätzlich sollte die Ausfallquote jedes Ausgangs erfasst werden, damit deutlich schlechter werdende Gruppen entfernt werden können.

Wenn dagegen alle Aufgaben denselben Ausgang nutzen, kann eine einzige Aufgabe die Verbindung beeinträchtigen und alle nachfolgenden Aufgaben treffen. Bei der Fehlersuche muss dann aus den Logs rückwärts rekonstruiert werden, welche Aufgabe die Ursache war.

Datenkonsistenz prüfen

Ein erfolgreicher Lauf bedeutet nicht automatisch korrekte Daten. Nach dem Speichern sollten einige Fragen beantwortbar sein: Passen die Anzahl abgeschlossener Aufgaben und die Zahl gespeicherter Zeilen zusammen, wie hoch ist der Anteil leerer Parsing-Ergebnisse, ist die Fehlquote kritischer Felder ungewöhnlich gestiegen und wie viele doppelte Zeilen gibt es?

Diese Prüfungen müssen nicht kompliziert sein. Stichproben pro Batch reichen aus, aber jemand muss die Ergebnisse ansehen. Im großen Maßstab können falsche Daten problematischer sein als gar keine Daten.

Welche Kennzahlen überwachen

Zu viele Kennzahlen helfen nicht. Einige wenige, die den Systemzustand abbilden, reichen aus.

  • Erfolgsquote und Verteilung der Fehlertypen, um zu sehen, welche Fehler zunehmen
  • Länge der Aufgabenwarteschlange und durchschnittliche Wartezeit; dauerhaft wachsender Rückstau deutet auf ein Missverhältnis zwischen Eingang und Verarbeitung hin
  • Anzahl aktiver Umgebungen und zugehöriger Prozesse; langfristiges einseitiges Wachstum weist häufig auf Lecks bei der Ressourcenfreigabe hin
  • Ausgabemenge pro Zeiteinheit, um zu erkennen, ob Rate-Limiting den Durchsatz begrenzt
  • Ausfallquote der Netzwerk-Ausgänge, um zu entscheiden, ob eine Gruppe von Knoten ersetzt werden sollte

Wenn sich nur eine dieser Kennzahlen über längere Zeit dauerhaft in eine Richtung bewegt, sollten zuerst Ressourcenfreigabe und Retry-Logik geprüft werden.

Die Umgebungsschicht separat verwalten

Zusammen betrachtet führen diese Punkte zum selben Schluss: Die Umgebungsschicht sollte unabhängig von den Skripten verwaltet werden. Für Environment-Pooling müssen Umgebungen zentral planbar sein, statt auf einzelne Skripte verteilt zu liegen; Ressourcenfreigabe braucht abfragbaren Status, statt von jedem Skript selbst aufgefangen zu werden; Wiederholungen mit einer anderen Umgebung oder einem anderen Ausgang funktionieren nur, wenn Umgebungen unabhängig geplant werden können.

Die Skripte kümmern sich um die Logik, die Umgebungsschicht um Ressourcen und Identität. In einer solchen Architektur übernimmt PurpleMark diese Ebene und stellt Umgebungsressourcen bereit, die stapelweise erstellt, an unabhängige Netzwerk-Ausgänge gebunden und nach Status abgefragt werden können.

Compliance-Grenzen

Skalierbarkeit bedeutet nicht, dass beliebig Daten gesammelt werden dürfen. Die robots-Regeln und Nutzungsbedingungen der Zielseite sind einzuhalten; personenbezogene Daten dürfen nicht erhoben und technische Schutzmaßnahmen nicht umgangen werden; außerdem ist die Anfragefrequenz so zu steuern, dass der normale Betrieb des Dienstes nicht beeinträchtigt wird. Stabilität ist eine technische Frage, die Zulässigkeit der Erfassung eine andere. Beides muss erfüllt sein.