Erstellen Sie zustandsbehaftete Streaming-Pipelines in Apache Spark, die Millionen aktiver Gaming-Gerätesitzungen verfolgen und Echtzeit-Heartbeats mit einer Latenz im Subsekundenbereich generieren.
von Neha Prabhu und Murali Talluri
In der Gaming-Branche zählt jede Millisekunde. Um die Personalisierung im Spiel voranzutreiben, Empfehlungs-Engines zu füttern und dynamische Entscheidungen für die Inhaltsplanung zu treffen, müssen Plattformen Sitzungsdaten für Millionen von Spielern weltweit mit einer Latenz von unter einer Sekunde verarbeiten.
Heute erfordert die Erfüllung dieser extrem niedrigen Latenzanforderungen keine unzusammenhängende Architektur mit mehreren Engines mehr. In diesem Blog untersuchen wir eine reale Implementierung des Apache Spark Real-Time Mode. Durch die Nutzung des neuen Operators transformWithState für komplexe zustandsabhängige Logik zeigen wir, wie Spark eine durchgängige Millisekunden-Performance liefert. Erfahren Sie, wie Ihr Team die Entwicklung beschleunigen und geschäftskritische operative Anwendungen mit dem vertrauten Structured Streaming-Ökosystem erstellen kann.
Für Gaming-Plattformen ist das Wissen darüber, welche Geräte wie lange aktiv sind, nicht nur eine Frage der Infrastruktur – es treibt das Geschäft an. Echtzeit-Sitzungsdaten ermöglichen personalisierte Erlebnisse im Spiel, füttern Empfehlungs-Engines, unterstützen Entscheidungen bei der Inhaltsplanung und liefern Statussignale für Geräte auf Millionen von Konsolen und PCs. Betriebsteams nutzen diese Daten, um Kindersicherungen durchzusetzen und ungewöhnliche Sitzungsmuster zu erkennen.
Sitzungsereignisse von Konsolen und PCs fließen in Kafka-Topics. Jedes Ereignis enthält eine device ID und eine session ID. Die device ID identifiziert die Konsole oder den PC; die session ID identifiziert die Spielsitzung. Es kann zu jedem Zeitpunkt nur eine Sitzung pro Gerät aktiv sein.
Die Pipeline deckt vier Szenarien ab:
Spark Structured Streaming im Micro-Batch-Modus kann zustandsabhängiges Sessionizing verarbeiten. Wenn der Anwendungsfall jedoch eine Präzision im Subsekundenbereich sowohl für die Eingabeverarbeitung als auch für die timergesteuerte Ausgabe erfordert, stößt Micro-Batch an seine Grenzen. In der Vergangenheit führte diese Lücke dazu, dass Teams eine zusätzliche spezialisierte Engine verwalten oder benutzerdefinierte Lösungen entwickeln mussten.
Mit Apache Flink: Zustandsverwaltung und Timer können zwar implementiert werden, aber die Einführung von Flink bedeutet die Übernahme eines völlig parallelen Ökosystems: ein separater Cluster, ein separates State-Backend, ein eigenes Bereitstellungsmodell, ein eigener Monitoring-Stack und eine eigene Codebasis – und das alles parallel zur Databricks-Plattform. Das Ergebnis sind eine Fragmentierung der Infrastruktur, betriebliche Komplexität sowie die Kosten für den Betrieb und das Personal für eine zweite Streaming-Engine.
Mit maßgeschneiderten Inhouse-Lösungen: Einige Teams entwickeln ihren eigenen Sessionizing-Dienst – beispielsweise ein Akka-basiertes Akteursmodell (Actor System), bei dem jedes Gerät einen Akteur erhält, der den Sitzungszustand, die Timer und die Heartbeat-Ausgabe verwaltet. Diese Lösungen bringen denselben Infrastruktur- und Betriebsaufwand wie Flink mit sich, bergen jedoch eine zusätzliche Herausforderung: Sie skalieren nicht. Die Verteilung von Millionen zustandsabhängiger Akteure über Knoten hinweg müssen Sie selbst entwickeln. Diese Systeme funktionieren anfangs, landen aber im Laufe der Zeit im reinen Wartungsmodus – stabil genug für den Betrieb, aber nicht einfach erweiterbar.
Heute schließt der Real-Time Mode diese Lücke für Kunden – und liefert Präzision im Subsekundenbereich mit denselben Spark-APIs, die Teams bereits verwenden, und das alles in einer einzigen, vereinheitlichten Engine.
transformWithState ist ein Operator der nächsten Generation in Spark Structured Streaming, der komplexe zustandsabhängige Verarbeitung flexibel und skalierbar macht. Zu den wichtigsten Funktionen gehören objektorientierte Zustandsverwaltung, zusammengesetzte Datentypen, timergesteuerte Logik, automatische TTL-Unterstützung und Schema-Evolution. In Kombination mit dem Real-Time Mode liefert er eine Präzision im Subsekundenbereich sowohl für die Eingabeverarbeitung als auch für die timergesteuerte Ausgabe.
Der Anwendungsfall des Gaming-Sessionizing erfordert zwei Dinge:
transformWithState liefert beides in einer einzigen StatefulProcessor-Klasse mit zwei dedizierten Methoden.
handleInputRows() reagiert auf eingehende Kafka-Ereignisse – verarbeitet Sitzungsstarts und -enden und verwaltet den Sessionizing-Zustand, während Ereignisse eingehen.
handleExpiredTimer() kümmert sich um alles, was dazwischen passiert – es wird ausgelöst, um proaktive Ausgaben wie Heartbeats und Timeouts zu erzeugen, unabhängig davon, ob neue Daten eingegangen sind.

Eine detaillierte Anleitung zur Architektur, Code-Implementierung und Überlegungen für die Produktion finden Sie in diesem begleitenden Blogbeitrag – dort gehen wir auf den StatefulProcessor-Code, den Timer-Lebenszyklus, Zustandsverwaltungsmuster und das Monitoring mit dem StreamingQueryListener ein. Die folgenden Ergebnisse veranschaulichen die Durchsatz- und Latenzeigenschaften der Pipeline und heben die signifikanten Latenzunterschiede zwischen dem Micro-Batch-Modus (MBM) und dem Real-Time Mode (RTM) hervor:
Um die Pipeline unter realistischer Last zu validieren, haben wir mit dem folgenden kontinuierlichen Durchsatz getestet:
Metrik (pro Minute) | Wert |
Eingangsereignisse (Sitzungsstarts + -enden) | ~500K |
Anzahl aktiver Sitzungen | ~4M |
Ausgegebene Heartbeat-Datensätze | ~8M |
Verstärkung von Eingang zu Ausgang | ~16x |
Der weitaus größte Teil der Ausgabe wird nicht durch eingehende Daten ausgelöst – er wird vollständig von handleExpiredTimer() generiert, das proaktiv Heartbeats nach einem Zeitplan ausgibt.
Die Latenz wird durchgängig gemessen – vom Zeitstempel des Kafka-Eingangs-Topics bis zum Zeitstempel des Ausgabe-Topics. Mit dem Real-Time Mode erreicht die Pipeline eine p99-Latenz von 432 ms – 20-mal schneller als im Micro-Batch-Modus.

Anwendungsfälle wie die Gaming-Sessionisierung erfordern Pipelines, die über die bloße Verarbeitung eingehender Ereignisse hinausgehen – sie müssen proaktiv regelmäßige Heartbeats senden, Millionen von gleichzeitigen Sessions verfolgen und den Zustand effizient verwalten. Dieses Muster beschränkt sich nicht nur auf Gaming. Jeder Workload, der eine Timer-gesteuerte Ausgabe erfordert – wie IoT-Heartbeats, Session-Tracking, Echtzeit-Alarmierung oder Geräteüberwachung –, kann auf dieselbe Weise aufgebaut werden.
Timer in transformWithState machen dies möglich. Eine einzige StatefulProcessor-Klasse verarbeitet den gesamten Session-Lebenszyklus – von der reaktiven Eingabeverarbeitung bis zur proaktiven, Timer-gesteuerten Ausgabe. In Kombination mit dem Real-Time Mode werden Eingabedatensätze verarbeitet und Timer mit einer Präzision im Subsekundenbereich ausgelöst – nicht erst beim nächsten Batch-Intervall, sondern sofort. Alles direkt in Databricks, ohne eine zweite Engine.
Wenn Sie bereits Structured Streaming-Pipelines im Micro-Batch-Modus ausführen und eine zweite Engine nutzen möchten, um geringere Latenzen zu erzielen, testen Sie zuerst den Real-Time Mode. Der Wechsel erfordert lediglich eine einzige Trigger-Änderung – kein Umschreiben von Code, kein Plattformwechsel:
Probieren Sie es selbst aus:
Der Real-Time Mode ist jetzt allgemein verfügbar.
(Dieser Blogbeitrag wurde mit KI-gestützten Tools übersetzt.) Originalbeitrag
Abonnieren Sie unseren Blog und erhalten Sie die neuesten Beiträge direkt in Ihren Posteingang.