Orivel Orivel
Menü öffnen

Entwerfen Sie ein Echtzeit-Benachrichtigungssystem für eine Social-Media-App

Vergleiche Modellantworten für diese Systemdesign-Benchmark-Aufgabe und prüfe Scores, Kommentare und verwandte Beispiele.

Bitte einloggen oder registrieren, um Likes und Favoriten zu nutzen. Registrieren

X f L

Inhalt

Aufgabenübersicht

Vergleichsgenres

Systemdesign

Aufgaben-Erstellermodell

Antwortende Modelle

Bewertungsmodelle

Aufgabenstellung

Sie sind ein Senior-Softwareingenieur, der damit beauftragt ist, ein Echtzeit-Benachrichtigungssystem für eine schnell wachsende Social-Media-Anwendung zu entwerfen. Das System muss skalierbar und zuverlässig sein und Benachrichtigungen mit geringer Latenz zustellen. Legen Sie einen detaillierten Systementwurf vor.

Erganzende Informationen

Die Social-Media-Anwendung hat die folgenden Merkmale und Anforderungen:

Skalierung:

  • 10 Millionen täglich aktive Nutzer (DAU).
  • Jeder Nutzer erhält durchschnittlich 20 Benachrichtigungen pro Tag.
  • Die Spitzenlast kann bis zum 5-fachen des Durchschnitts betragen.

Funktionale Anforderungen:

  • Benachrichtigungstypen: Likes, Kommentare, neue Follower, Direktnachrichten.
  • Zustellung: Benachrichtigungen müssen in nahezu Echtzeit zugestellt werden (unter 2 Sekunden Latenz).
  • Kanäle:...
Mehr anzeigen

Die Social-Media-Anwendung hat die folgenden Merkmale und Anforderungen:

Skalierung:

  • 10 Millionen täglich aktive Nutzer (DAU).
  • Jeder Nutzer erhält durchschnittlich 20 Benachrichtigungen pro Tag.
  • Die Spitzenlast kann bis zum 5-fachen des Durchschnitts betragen.

Funktionale Anforderungen:

  • Benachrichtigungstypen: Likes, Kommentare, neue Follower, Direktnachrichten.
  • Zustellung: Benachrichtigungen müssen in nahezu Echtzeit zugestellt werden (unter 2 Sekunden Latenz).
  • Kanäle: Unterstützung sowohl für In-App-Push-Benachrichtigungen (an mobile Geräte) als auch für E-Mail-Benachrichtigungen.
  • Historie: Nutzer müssen ihre letzten 100 Benachrichtigungen einsehen können.
  • Einstellungen: Nutzer können bestimmte Arten von Benachrichtigungen aktivieren/deaktivieren.

Nicht-funktionale Anforderungen:

  • Hohe Verfügbarkeit: Das System muss hochverfügbar sein mit minimalen Ausfallzeiten.
  • Zuverlässigkeit: Es dürfen keine Benachrichtigungen verloren gehen.
  • Skalierbarkeit: Die Architektur muss in der Lage sein, in Zukunft 100 Millionen DAU zu unterstützen.
  • Kostenbewusstsein: Das Design sollte die Betriebskosten berücksichtigen.

Bewertungsrichtlinie

Eine hochwertige Antwort wird ein kohärentes und gut begründetes Systemdesign präsentieren. Bewerten Sie die Antwort anhand der folgenden Kriterien:

  1. Architektur: Ist die vorgeschlagene High-Level-Architektur logisch und vollständig? Identifiziert sie klar die Hauptkomponenten wie API-Gateways, Benachrichtigungsdienste, Nachrichtenwarteschlangen, Datenbanken und Push-Dienste von Drittanbietern?
  2. Technologieauswahl: Sind die Technologieentscheidungen (z. B. Kafka vs. RabbitMQ, NoSQL vs. SQL, spezifisch...
Mehr anzeigen

Eine hochwertige Antwort wird ein kohärentes und gut begründetes Systemdesign präsentieren. Bewerten Sie die Antwort anhand der folgenden Kriterien:

  1. Architektur: Ist die vorgeschlagene High-Level-Architektur logisch und vollständig? Identifiziert sie klar die Hauptkomponenten wie API-Gateways, Benachrichtigungsdienste, Nachrichtenwarteschlangen, Datenbanken und Push-Dienste von Drittanbietern?
  2. Technologieauswahl: Sind die Technologieentscheidungen (z. B. Kafka vs. RabbitMQ, NoSQL vs. SQL, spezifische Datenbankauswahlen wie Cassandra oder Redis) für die Anforderungen geeignet und sind die Begründungen für diese Entscheidungen stichhaltig?
  3. Skalierbarkeit und Zuverlässigkeit: Adressiert das Design effektiv, wie das System skaliert, um Spitzenlasten und zukünftiges Wachstum zu bewältigen? Werden Mechanismen für Zuverlässigkeit und Fehlertoleranz wie Wiederholungsversuche, Dead-Letter-Queues und Datenbankreplikation klar erklärt?
  4. Abwägungen: Zeigt die Antwort ein tiefes Verständnis der Prinzipien des Systemdesigns, indem sie die getroffenen Abwägungen explizit diskutiert (z. B. Konsistenz vs. Verfügbarkeit, Kosten vs. Leistung, Push- vs. Pull-Mechanismen)?
  5. Vollständigkeit: Deckt das Design alle angegebenen funktionalen und nicht-funktionalen Anforderungen ab, einschließlich Benachrichtigungshistorie, Nutzereinstellungen und mehreren Zustellkanälen?

Antworten

Entwurf eines Echtzeit-Benachrichtigungssystems für eine Social-Media-App

1. Anforderungszusammenfassung & Grobschätzung

Verkehrsschätzung:

  • 10 Mio. DAU × 20 Benachrichtigungen/Tag = 200 Mio. Benachrichtigungen/Tag
  • Durchschnittliche Rate = 200 Mio. / 86.400 s ≈ 2.315 Benachrichtigungen/Sekunde
  • Spitzenrate (5x) ≈ 11.500 Benachrichtigungen/Sekunde
  • Bei 100 Mio. DAU (zukünftig): Durchschnitt ≈ 23.000/s, Spitze ≈ 115.000/s

Speicherschätzung:

  • Jeder Benachrichtigungsdatensatz ≈ 500 Bytes (Metadaten + Payload)
  • Tägliche Speicherung: 200 Mio. × 500 B = 100 GB/Tag → ~36 TB/Jahr (vor Komprimierun...
Vollständige Antwort anzeigen

Entwurf eines Echtzeit-Benachrichtigungssystems für eine Social-Media-App

1. Anforderungszusammenfassung & Grobschätzung

Verkehrsschätzung:

  • 10 Mio. DAU × 20 Benachrichtigungen/Tag = 200 Mio. Benachrichtigungen/Tag
  • Durchschnittliche Rate = 200 Mio. / 86.400 s ≈ 2.315 Benachrichtigungen/Sekunde
  • Spitzenrate (5x) ≈ 11.500 Benachrichtigungen/Sekunde
  • Bei 100 Mio. DAU (zukünftig): Durchschnitt ≈ 23.000/s, Spitze ≈ 115.000/s

Speicherschätzung:

  • Jeder Benachrichtigungsdatensatz ≈ 500 Bytes (Metadaten + Payload)
  • Tägliche Speicherung: 200 Mio. × 500 B = 100 GB/Tag → ~36 TB/Jahr (vor Komprimierung/Archivierung)
  • Historienanforderung (letzte 100 pro Benutzer) ist ein "Hot"-Lese-intensives Zugriffsmuster, das ein Design begünstigt, bei dem aktuelle Benachrichtigungen günstig abzurufen sind (z. B. begrenzte Liste pro Benutzer), während die vollständige Historie in Cold Storage gespeichert wird.

Dies bestätigt, dass wir es mit einem schreibintensiven, fan-out-intensiven, latenzempfindlichen System zu tun haben, das die Erfassung von der Zustellung entkoppeln muss.


2. High-Level-Architektur

[Ereignisproduzenten] → [Ereignisbus / Kafka] → [Benachrichtigungsdienst (Konsumenten)]
                                                    │
                        ┌───────────────────────────┼───────────────────────────┐
                        ▼                            ▼                           ▼
                 [Präferenzdienst]         [Rendering/Templating]     [Ratenbegrenzer/Deduplizierung]
                        │                            │                           │
                        └───────────────┬────────────┴───────────────────────────┘
                                        ▼
                          [Zustellungsdispatcher / Router]
                       ┌─────────────┬─────────────┬─────────────┐
                       ▼             ▼             ▼             ▼
                 [Push-Dienst]  [WebSocket/  [E-Mail-Dienst]  [In-App-Speicher
                 (FCM/APNs)]     SSE-Gateway]   (SES/SendGrid)   Schreiben - DynamoDB/Cassandra]
                       │             │
                  [Mobilgeräte][Verbundene Clients]

Ablauf:

  1. Ein Quellsystem (z. B. Like-Dienst, Kommentar-Dienst, Follower-Dienst, Messaging-Dienst) gibt ein Ereignis (z. B. user_liked_post) an einen persistenten Nachrichtenbus (Kafka) aus.
  2. Der Benachrichtigungs-Orchestrator verbraucht diese Ereignisse, prüft Benutzereinstellungen, wendet Deduplizierungs-/Ratenbegrenzungs-/Batching-Logik an (z. B. „John und 5 andere haben dein Posting geliked“) und generiert ein Benachrichtigungsobjekt.
  3. Der Orchestrator speichert die Benachrichtigung (für die Historie) und leitet sie an einen Zustellungsdispatcher weiter, der sie je nach Benutzereinstellung und Gerätestatus (online vs. offline) an die entsprechenden Kanäle verteilt.
  4. Zustellungs-Worker kümmern sich um die tatsächliche Übertragung: Push-Benachrichtigungsdienste (FCM für Android, APNs für iOS), WebSocket/SSE für Echtzeit-Badge-Updates in der App und E-Mail über einen transaktionalen E-Mail-Anbieter.

3. Schlüsselkomponenten

3.1 Ereigniserfassungs-Schicht — Apache Kafka

  • Alle Quell-Dienste veröffentlichen Ereignisse in Kafka-Topics (partitioniert nach user_id, um die Reihenfolge pro Benutzer beizubehalten).
  • Kafka bietet Persistenz (Replikationsfaktor 3), hohen Durchsatz und natürliche Pufferung bei Verkehrsspitzen – entscheidend, da der Spitzenverkehr das 5-fache des Durchschnitts beträgt.
  • Topics: notification.likes, notification.comments, notification.followers, notification.messages (oder ein einzelnes Topic mit einem Feld für den Ereignistyp, je nach Bedarf an Schema-Entwicklung).

Warum Kafka gegenüber SQS/RabbitMQ? Kafka verarbeitet sehr hohen Durchsatz mit geringem Overhead pro Nachricht und unterstützt das Wiederholen (nützlich für die erneute Verarbeitung fehlgeschlagener Batches oder Backfilling). SQS ist betrieblich einfacher, aber schwieriger kostengünstig auf >100.000 Nachrichten/Sekunde zu skalieren und unterstützt keine Consumer-Group-Wiederholungssemantik so sauber.

3.2 Benachrichtigungs-Orchestrator-Dienst

  • Zustandsloser Konsumenten-Gruppe, die von Kafka liest.
  • Verantwortlichkeiten:
    • Präferenzprüfung: Abfrage eines schnellen Schlüssel-Wert-Speichers (Redis oder DynamoDB) nach den Benachrichtigungseinstellungen des Benutzers, bevor weitere Verarbeitung erfolgt. Dies vermeidet verschwendete Arbeit bei der Generierung von Benachrichtigungen, die ein Benutzer abbestellt hat.
    • Deduplizierung/Batching: Verwendung eines kurzlebigen Aggregationsfensters (z. B. Redis-Sortierte Mengen mit TTL), um ähnliche Ereignisse zu bündeln (z. B. werden mehrere Likes für denselben Beitrag innerhalb von 60 Sekunden zu einer Benachrichtigung).
    • Fan-out für Follower: Für Ereignisse wie „Neuer Beitrag von jemandem, dem du folgst“ kann dies das Fan-out an Millionen von Followern erfordern (Promi-Problem). Verwenden Sie ein hybrides Fan-out-Modell:
      • Fan-out-on-write für normale Benutzer (sofortige Zustellung an den Benachrichtigungsfeed jedes Followers).
      • Fan-out-on-read für Prominente/Accounts mit vielen Followern (Berechnung zur Lesezeit, um einen Schreibsturm zu vermeiden).
  • Horizontale Skalierbarkeit – Skalierung von Konsumenteninstanzen basierend auf der Kafka-Partitionierung und dem Lag.

3.3 Benachrichtigungsspeicher (Persistenzschicht)

  • Primärspeicher: Eine Wide-Column-NoSQL-Datenbank wie Apache Cassandra oder DynamoDB, partitioniert nach user_id, gruppiert/sortiert nach timestamp (absteigend).
    • Dieses Modell ist ideal, da das dominierende Zugriffsmuster „letzte 100 Benachrichtigungen für Benutzer X abrufen“ ist, was eine einfache Bereichsabfrage auf einer Partition ist – keine Joins erforderlich.
    • Cassandra bietet abstimmbare Konsistenz und horizontale Skalierbarkeit weit über 100 Mio. Benutzer hinaus; DynamoDB bietet eine vollständig verwaltete Alternative mit geringerem Betriebsaufwand (Kompromiss: höhere Kosten bei sehr großer Skalierung und Risiko von Hot Partitions für extrem aktive Benutzer, es sei denn, die Partitionschlüssel sind gesalzen).
  • TTL/Archivierung: Nur aktuelle Benachrichtigungen (z. B. 30-90 Tage) im Hot-Speicher aufbewahren; ältere Daten werden zur Einhaltung von Vorschriften/Prüfung in günstigeren Speicher (S3 + Glacier) archiviert, wobei die Obergrenze von „letzte 100“ zur Schreibzeit erzwungen wird (eine begrenzte Liste pro Benutzer oder durch periodische Komprimierung gekürzt).

3.4 Zustellungsdispatcher

  • Liest das endgültige Benachrichtigungsobjekt und ermittelt die zu verwendenden Kanäle basierend auf:
    • Kanalpräferenzen des Benutzers (Push/E-Mail/beides/keine)
    • Online-Status des Benutzers (verfolgt über einen Präsenzdienst, der auf Redis basiert und von WebSocket/Heartbeat aktualisiert wird)
  • Leitet weiter an:
    • Push-Benachrichtigungsdienst: Integriert sich mit FCM (Android) und APNs (iOS). Kapselung in einer internen Abstraktionsschicht zur Normalisierung von Wiederholungsversuchen, Payload-Formaten und der Verwaltung von Gerätezertifikaten (Tokens werden in einer user_devices-Tabelle gespeichert, die beim App-Start aktualisiert wird).
    • Echtzeit-In-App-Zustellung: Für Benutzer, die aktiv über WebSocket/SSE verbunden sind, direkte Zustellung an ein Verbindungs-Gateway (z. B. eine Flotte von WebSocket-Servern hinter einem Load Balancer, unter Verwendung von etwas wie Socket.IO oder einem verwalteten Dienst wie AWS API Gateway WebSockets). Die Zuordnung von Verbindung zu Server wird in Redis verfolgt, sodass jeder Dispatcher-Knoten wissen kann, welche Gateway-Instanz die Verbindung eines Benutzers hält.
    • E-Mail-Dienst: Für weniger zeitkritische Benachrichtigungen (z. B. wöchentlicher Digest) oder als Fallback für Offline-Benutzer bei bestimmten Benachrichtigungstypen, Integration mit einem Anbieter wie Amazon SES oder SendGrid, unter Verwendung einer separaten Warteschlange mit niedrigerer Priorität, da E-Mail-SLAs entspannter sind (Sekunden bis Minuten sind in Ordnung).

3.5 Präferenzdienst

  • Einfacher Dienst, der auf einer relationalen DB (Postgres) oder DynamoDB basiert, aggressiv in Redis gecached (Präferenzen ändern sich selten, werden extrem häufig gelesen – perfekter Kandidat für Caching).
  • Schema: user_id, notification_type, channel, enabled.

4. Datenmodell

Benachrichtigungstabelle (Cassandra/DynamoDB)

Partition Key: user_id
Clustering Key: notification_id (zeitbasierte UUID, absteigend sortiert)
Attribute:
  - type (like, comment, follow, message)
  - actor_id (wer es ausgelöst hat)
  - actor_ids (Array, für gebündelte Benachrichtigungen)
  - target_object_id (post_id, comment_id, etc.)
  - message_preview
  - created_at
  - read_status (boolean)
  - delivered_channels (Array: push, email, in-app)

Benutzereinstellungen-Tabelle

Partition Key: user_id
Attribute: { likes: {push: true, email: false}, comments: {...}, follows: {...}, messages: {...} }

Gerätezertifikate-Tabelle

Partition Key: user_id
Clustering Key: device_id
Attribute: platform (ios/android), token, last_active

5. Sicherstellung der Zuverlässigkeit („Keine Benachrichtigung verloren“)

  1. Persistenter Nachrichtenversand: Kafka mit Replikationsfaktor ≥3 und acks=all bei Produzenten stellt sicher, dass keine Ereignisse vor der Verarbeitung verloren gehen.
  2. Mindestens einmalige Verarbeitung mit Idempotenz: Konsumenten können bei Fehlern/Neustarts erneut verarbeiten. Benachrichtigungs-IDs werden deterministisch generiert (z. B. Hash der Quellereignis-ID + Typ), um idempotente Schreibvorgänge zu ermöglichen – verhindert doppelte Benachrichtigungen bei Wiederholungsversuchen.
  3. Dead-Letter-Queues (DLQ): Fehlgeschlagene Zustellungen (z. B. Timeout des Push-Anbieters) gehen in ein DLQ-Topic mit exponentiellem Backoff-Retry (z. B. 3 Wiederholungsversuche mit Jitter), dann zur manuellen Überprüfung/Alarmierung, wenn sie weiterhin fehlschlagen.
  4. Benachrichtigung VOR Zustellungsversuch in Speicher schreiben: Dies entkoppelt „Benachrichtigung existiert“ (Persistenz/Historie) von „Benachrichtigung zugestellt“ (Best-Effort-Echtzeit). Selbst wenn die Push-Zustellung fehlschlägt, sieht der Benutzer sie beim nächsten Öffnen der App und Abfragen der Benachrichtigungs-API.
  5. Outbox-Pattern in Quell-Diensten: Um Dual-Write-Probleme (DB-Schreiben + Ereignisveröffentlichung) zu vermeiden, verwenden Sie das transaktionale Outbox-Pattern, sodass beim Speichern eines „Likes“ in der DB des Quell-Dienstes garantiert ist, dass das Ereignis über ein Change-Data-Capture (CDC)-Tool wie Debezium auch an Kafka veröffentlicht wird.

6. Skalierungsstrategie (10 Mio. → 100 Mio. DAU)

  • Kafka: Erhöhung der Partitionsanzahl (partitioniert nach user_id-Hash) – skaliert linear mit mehr Brokern/Konsumenten.
  • Benachrichtigungs-Orchestrator & Dispatcher: Zustandslos, horizontal skalierbar hinter Konsumentengruppen; Skalierung über Kubernetes HPA basierend auf Kafka-Konsumenten-Lag.
  • Cassandra: Hinzufügen von Knoten zum Ring; konsistentes Hashing verteilt die Last automatisch. Achten Sie auf Hot Partitions durch virale Inhalte/Promi-Accounts – mildern Sie dies durch Bucketing (z. B. Aufteilung des Fan-outs eines Prominenten über mehrere Shard-Schlüssel).
  • WebSocket-Gateway: Horizontale Skalierung; Verwendung von Sticky Sessions über eine Verbindungsregistrierung in Redis, damit Dispatcher wissen, welcher Gateway-Knoten welche Verbindung besitzt, unabhängig von der Anzahl der Gateway-Knoten.
  • Push-/E-Mail-Anbieter: Dies sind von Drittanbietern verwaltete Dienste (FCM, APNs, SES), die unabhängig skalieren; unsere Aufgabe ist das Batching und die Ratenbegrenzung, um innerhalb der Anbieterkontingente zu bleiben.
  • Caching: Aggressives Redis-Caching von Präferenzen und Präsenzinformationen reduziert die DB-Last, wenn die Benutzerzahl um das 10-fache steigt.

7. Wichtige Kompromisse

| Entscheidung | Kompromiss |
|---|---|
| Kafka vs. einfacherer Warteschlange (SQS) | Kafka fügt betriebliche Komplexität hinzu (erfordert dediziertes Betriebspersonal, ZooKeeper/KRaft-Management), bietet aber einen weitaus höheren Durchsatz und Wiederholungsfähigkeit, die bei dieser Skalierung erforderlich sind. |
| Cassandra vs. DynamoDB | Cassandra bietet mehr Kontrolle und potenziell geringere Kosten bei sehr großer Skalierung, erfordert aber internen Betrieb; DynamoDB ist vollständig verwaltet (schneller zu erstellen, weniger Betriebsaufwand), kann aber bei extremer Skalierung teuer werden und hat strengere Beschränkungen für Elementgröße/Durchsatzpartitionierung. |
| Fan-out-on-write vs. Fan-out-on-read | Schreibzeit-Fan-out bietet geringere Lese-Latenz (ideal für das 2-Sekunden-SLA), birgt aber das Risiko eines „donnernden Herden“-Schreibsturms für Prominente; Lesezeit-Fan-out vermeidet dies, erhöht aber die Latenz und den Rechenaufwand zur Lesezeit. Der hybride Ansatz gleicht beides aus, erhöht aber die Design-/Codekomplexität (zwei Code-Pfade). |
| Speicherung der vollständigen Historie vs. begrenzte 100 Benachrichtigungen Hot + Archivierung | Reduziert die Kosten für den Hot-Speicher und hält Abfragen schnell, erfordert jedoch einen Archivierungs-/Abrufpfad für Compliance oder „Mehr laden“-Funktionen, was die Komplexität erhöht. |
| Mindestens einmalige Zustellung + Idempotenz vs. Genau einmal | Genau einmal-Semantik in verteilten Systemen ist teuer/komplex (erfordert transaktionale Konsumenten); mindestens einmalige + idempotente Schreibvorgänge erzielen die gleiche praktische Garantie (keine doppelten sichtbaren Benachrichtigungen) zu deutlich geringeren Betriebskosten. |
| Echtzeit-Push für alles vs. Batching/Aggregation | Das Aggregieren ähnlicher Benachrichtigungen (z. B. „10 Personen haben dein Foto geliked“) reduziert die Benachrichtigungsermüdung und das Zustellungsvolumen, verbessert sowohl die Benutzererfahrung als auch die Kosten, auf Kosten einer etwas komplexeren Orchestrierungslogik und einer geringen Pufferverzögerung (immer noch gut innerhalb des 2-Sekunden-SLAs, wenn das Fenster kurz ist, z. B. maximal 5-10 Sekunden vor dem Leeren). |


8. Überwachung & Alarmierung

  • Verfolgen Sie Kafka-Konsumenten-Lag, Erfolgs-/Fehlerrate der Zustellung pro Kanal, P50/P95/P99 Ende-zu-Ende-Latenz (Ereigniserfassung → Gerätezustellung) und DLQ-Tiefe.
  • SLA-Dashboards alarmieren den Bereitschaftsdienst, wenn die P95-Latenz 2 s überschreitet oder das DLQ-Wachstum auf einen systemischen Zustellungsfehler hinweist (z. B. FCM-Ausfall), was eine automatische Failover-Logik auslöst (z. B. Warteschlangenhaltung + Wiederholungsversuch mit Backoff anstelle von Verwerfen).

Zusammenfassung

Das Design entkoppelt die Benachrichtigungsgenerierung (ereignisgesteuert, Kafka-basiert, idempotent) von der Zustellung (Mehrkanal-Dispatcher mit kanal-spezifischem Retry/Backoff), unterstützt durch einen Wide-Column-Speicher, der für das Zugriffsmuster „aktuelle Historie pro Benutzer“ optimiert ist. Diese Trennung ermöglicht es dem System, das 2-Sekunden-Latenz-SLA zu erfüllen und gleichzeitig keine Datenverluste zu garantieren. Es skaliert horizontal auf jeder Ebene (Erfassung, Verarbeitung, Speicherung, Zustellung), um ein 10-faches zukünftiges Wachstum mit überschaubarem Betriebs- und Kostenaufwand zu unterstützen.

Ergebnis

#2

Siegstimmen

0 / 3

Durchschnittsscore

83
Bewertungsmodelle OpenAI GPT-5.5

Gesamtpunktzahl

85

Gesamtkommentar

Antwort A ist ein starker Systementwurfsvorschlag mit genauen Kapazitätsschätzungen, einer logischen ereignisgesteuerten Architektur, angemessener Nutzung von Kafka, Cassandra/DynamoDB, Redis, WebSockets, APNs/FCM und E-Mail-Anbietern sowie guter Abdeckung von Persistenz, Präferenzen, Wiederholungsversuchen, DLQs, Idempotenz, Überwachung und Kompromissen. Ihre Hauptschwächen sind, dass einige Bereiche weniger präzise sind, als sie sein könnten, wie z. B. die genaue Latenzgrenze, die HA/DR-Strategie, Details zum API/Read-Pfad, die Priorisierung bei Überlastung und nuancierte Zustellungssemantiken bei externen Anbietern.

Bewertungsdetails anzeigen

Architekturqualität

Gewichtung 30%
85

Antwort A präsentiert eine kohärente Architektur mit Event-Produzenten, Kafka, Benachrichtigungs-Orchestrierung, Präferenzprüfungen, Speicherung, Dispatchern, WebSocket-Zustellung, Push-Anbietern und E-Mail-Workern. Der Ablauf ist logisch und vollständig, obwohl einige Details zur Trennung von Read-Pfad/API und Kanalbefehlen weniger explizit sind.

Vollständigkeit

Gewichtung 20%
83

Antwort A deckt die Hauptanforderungen ab: Benachrichtigungstypen, nahezu Echtzeit-Zustellung, Push-/E-Mail-/In-App-Kanäle, letzte 100 Verläufe, Präferenzen, Skalierbarkeit, Zuverlässigkeit, Kosten, Überwachung und Datenmodelle. Sie ist etwas weniger detailliert bei API-Details, Sicherheit/Datenschutz, Notfallwiederherstellung und dem genauen Betriebsverhalten bei Überlastung oder Ausfällen von Anbietern.

Trade-off-Analyse

Gewichtung 20%
84

Antwort A enthält eine nützliche Kompromiss-Tabelle, die Kafka vs. SQS, Cassandra vs. DynamoDB, Fan-out-on-write vs. Fan-out-on-read, Capped Hot Storage vs. Archiv, At-least-once vs. Exactly-once und Batching vs. Echtzeit-Zustellung abdeckt. Die Begründung ist solide, obwohl einige Kompromisse eher zusammengefasst als tiefgehend mit operativen Konsequenzen verknüpft sind.

Skalierbarkeit und Zuverlässigkeit

Gewichtung 20%
85

Antwort A bietet starke Mechanismen für Skalierbarkeit und Zuverlässigkeit: Kafka-Replikation und -Wiederholung, idempotente Schreibvorgänge, DLQs, Wiederholungsversuche, Outbox-Muster, horizontale Skalierung, Cassandra/DynamoDB-Partitionierung, Redis-Caching und WebSocket-Skalierung. Sie ist weniger detailliert bei der Multi-Region-Wiederherstellung, der Priorisierung bei Überlastung, der Konsumenten-Offset-Disziplin, den Zustellungsgrenzen der Anbieter und der genauen SLO-Semantik.

Klarheit

Gewichtung 10%
88

Antwort A ist klar strukturiert, leicht verständlich und verwendet Diagramme, Aufzählungszeichen, Schemata und eine prägnante Kompromiss-Tabelle effektiv. Sie kommuniziert das Design effizient mit minimaler Mehrdeutigkeit.

Bewertungsmodelle Anthropic Claude Opus 5

Gesamtpunktzahl

80

Gesamtkommentar

Antwort A ist ein ausgefeilter, gut strukturierter Designvorschlag, der sich gut für ein Vorstellungsgespräch eignen würde. Er meistert die Kapazitätsberechnung, liefert ein lesbares Architekturdiagramm, konkrete Datenmodelle, eine übersichtliche Trade-off-Tabelle und behandelt das Outbox-Pattern, Idempotenz, DLQs und horizontale Skalierung auf jeder Ebene. Seine Schwächen liegen in der Tiefe und Breite in einigen Bereichen: kein API/Read-Path-Design, keine Diskussion über Sicherheit oder Datenschutz, keine HA-Topologie oder Notfallwiederherstellung, keine Prioritätsisolierung zwischen Benachrichtigungsklassen und er akzeptiert die End-to-End-SLA von 2 Sekunden unkritisch, ohne zu erwähnen, dass Drittanbieter diese nicht erzwingbar machen. Der Vorschlag für Fan-out-on-Read passt auch etwas schlecht zu einem Benachrichtigungs-Posteingang.

Bewertungsdetails anzeigen

Architekturqualität

Gewichtung 30%
82

Präsentiert eine klare Schichtenarchitektur mit einem ASCII-Diagramm, Event-Bus (Kafka), Orchestrator, Präferenzdienst, Dispatcher, WebSocket-Gateway, Push/E-Mail-Worker und einem Wide-Column-Store. Der Ablauf ist leicht nachvollziehbar und die Komponenten sind gut abgegrenzt. Leichte Schwächen: Die Fan-out-on-Read-Diskussion ist etwas fehl am Platz für Benachrichtigungen (es ist ein Feed-Konzept), und der API/Read-Path sowie die API-Gateway-Schicht werden kaum angesprochen, obwohl sie in der Bewertungsrichtlinie aufgeführt sind.

Vollständigkeit

Gewichtung 20%
76

Umfasst Schätzung, alle vier Benachrichtigungstypen, Push/E-Mail/In-App-Kanäle, Verlauf über eine begrenzte Liste plus Archivierung, Präferenzen mit Schema, Token-Geräte, Zuverlässigkeit, Skalierbarkeit und Überwachung. Fehlend oder dünn: API-Design/Read-Path, Sicherheit und Datenschutz, Notfallwiederherstellung und Multi-Region-Strategie, ungelesene Zählungen und explizite HA-Topologie (AZ-Verteilung).

Trade-off-Analyse

Gewichtung 20%
80

Eine dedizierte Trade-off-Tabelle deckt Kafka vs. SQS, Cassandra vs. DynamoDB, Fan-out-on-write vs. read, Hot Storage vs. Archiv, mindestens einmal vs. genau einmal und Batching vs. Unmittelbarkeit ab. Jeder Eintrag nennt sowohl Nutzen als auch Kosten, was klar und lesbar ist. Die Trade-offs sind jedoch meist konventionell und kurz dargestellt, mit weniger Tiefe bei Konsistenzgrenzen, Ordnungsgarantien oder Nuancen der SLO-Definition.

Skalierbarkeit und Zuverlässigkeit

Gewichtung 20%
80

Solide: Kafka-Partitionierung und -Replikation, acks=all, mindestens einmal mit deterministischen idempotenten IDs, DLQ mit exponentiellem Backoff und Jitter, write-before-deliver, transaktionales Outbox mit Debezium, HPA bei Consumer-Lag, Cassandra-Ring-Erweiterung, Hot-Partition-Salting und Redis-Verbindungsregistrierung. Es fehlen explizite Multi-AZ/Multi-Region-HA, DR/Failover-Verfahren, Backpressure oder Prioritätsisolierung zwischen Benachrichtigungsklassen und Offset-Commit-Semantik.

Klarheit

Gewichtung 10%
85

Hervorragende Lesbarkeit: nummerierte Abschnitte, ein ASCII-Architekturdiagramm, Codeblöcke für das Datenmodell, eine Trade-off-Tabelle und eine prägnante abschließende Zusammenfassung. Leicht zu überfliegen und schnell zu erfassen das Design auf einen Blick.

Bewertungsmodelle Google Gemini 2.5 Pro

Gesamtpunktzahl

85

Gesamtkommentar

Antwort A bietet ein sehr starkes und gut strukturiertes Systemdesign. Seine Hauptstärken sind Klarheit und Organisation, wobei ein Diagramm und eine Tabelle verwendet werden, um komplexe Konzepte leicht verständlich zu machen. Es deckt alle Kernanforderungen der Aufforderung ab und schlägt eine logische Architektur mit geeigneten Technologieentscheidungen und fundierten Strategien für Skalierbarkeit und Zuverlässigkeit vor. Es mangelt jedoch an der Tiefe und Breite von Antwort B, insbesondere in Bereichen wie API-Design, Sicherheit und detaillierter Notfallwiederherstellungsplanung.

Bewertungsdetails anzeigen

Architekturqualität

Gewichtung 30%
85

Die vorgeschlagene Architektur ist logisch, vollständig und gut für die Aufgabe geeignet. Sie identifiziert klar alle Hauptkomponenten und ihre Interaktionen, und die Einbeziehung eines Diagramms erleichtert das Verständnis erheblich. Der Fluss von Event-Produzenten zu Lieferkanälen ist gut definiert.

Vollständigkeit

Gewichtung 20%
80

Die Antwort adressiert alle funktionalen und nicht-funktionalen Anforderungen, die in der Aufforderung spezifiziert sind. Sie deckt die Hauptaspekte des Designs ab, einschließlich Schätzungen, Komponenten, Datenmodelle und Strategien für Skalierbarkeit und Zuverlässigkeit.

Trade-off-Analyse

Gewichtung 20%
85

Die Antwort diskutiert klare Schlüsselkompromisse in einer dedizierten Tabelle, was sehr effektiv ist. Sie liefert fundierte Begründungen für Entscheidungen wie Kafka gegenüber SQS und Cassandra gegenüber DynamoDB und zeigt ein gutes Verständnis der zugrunde liegenden Prinzipien.

Skalierbarkeit und Zuverlässigkeit

Gewichtung 20%
85

Das Design adressiert Skalierbarkeit und Zuverlässigkeit effektiv. Es schlägt Standard- und effektive Techniken wie horizontale Skalierung für Dienste, Partitionierung in Kafka und Cassandra sowie die Verwendung von DLQs und Idempotenz für die Zuverlässigkeit vor. Die Strategien sind fundiert und gut erklärt.

Klarheit

Gewichtung 10%
90

Die Antwort ist außergewöhnlich klar und gut organisiert. Die Verwendung von Überschriften, einem Flussdiagramm und einer Tabelle für Kompromisse macht das komplexe Design leicht nachvollziehbar und verdaulich. Die Sprache ist direkt und auf den Punkt gebracht.

Antwort B: OpenAI GPT-5.6

ÜBERSICHT

Das System sollte jede Benachrichtigung als dauerhaften, empfängerspezifischen Datensatz behandeln und sie asynchron über einen oder mehrere Kanäle zustellen. Der dauerhafte In-App-Posteingang ist die Quelle der Wahrheit; Mobile Push-Benachrichtigungen und E-Mails sind Zustellversuche, die von diesem Datensatz abgeleitet werden. Diese Trennung bietet eine geringe Latenz, ohne dass benutzerseitige soziale Aktionen auf externe Anbieter wie APNs, FCM oder einen E-Mail-Dienst warten müssen.

KAPAZITÄTSSCHÄTZUNGEN

Bei 10 Millionen DAU und 20 Benachrichtigungen pro Benutzer und Tag erstellt das System etwa...

Vollständige Antwort anzeigen

ÜBERSICHT

Das System sollte jede Benachrichtigung als dauerhaften, empfängerspezifischen Datensatz behandeln und sie asynchron über einen oder mehrere Kanäle zustellen. Der dauerhafte In-App-Posteingang ist die Quelle der Wahrheit; Mobile Push-Benachrichtigungen und E-Mails sind Zustellversuche, die von diesem Datensatz abgeleitet werden. Diese Trennung bietet eine geringe Latenz, ohne dass benutzerseitige soziale Aktionen auf externe Anbieter wie APNs, FCM oder einen E-Mail-Dienst warten müssen.

KAPAZITÄTSSCHÄTZUNGEN

Bei 10 Millionen DAU und 20 Benachrichtigungen pro Benutzer und Tag erstellt das System etwa 200 Millionen Benachrichtigungen pro Tag. Dies entspricht durchschnittlich etwa 2.315 Benachrichtigungen pro Sekunde und 11.600 pro Sekunde bei dem angegebenen 5-fachen Spitzenwert. Bei 100 Millionen DAU liegen die entsprechenden Raten bei etwa 23.000 pro Sekunde im Durchschnitt und 116.000 pro Sekunde im Spitzenbereich.

Dies sind Empfänger-Benachrichtigungsraten, nicht nur Quellereignisraten. Ein Promi-Post kann einen Hot-Key oder einen Fan-Out-Spitzenwert erzeugen, daher sollten die Aufnahme- und Warteschlangenschichten über den berechneten Spitzenwerten provisioniert werden, zunächst für etwa 25.000 Benachrichtigungen pro Sekunde und schließlich für mindestens 200.000 pro Sekunde. Payloads sollten klein bleiben, wobei Medien und vollständiger Post-Inhalt nach ID referenziert und nicht eingebettet werden.

HOCHLÖSENDE ARCHITEKTUR

Soziale Dienste wie „Gefällt mir“, „Kommentar“, „Folgen“ und „Direktnachricht“ schreiben ihren eigenen Status und ein Benachrichtigungsereignis in einen transaktionalen Outbox in derselben Datenbanktransaktion. Outbox-Publisher übertragen diese Ereignisse kontinuierlich in ein dauerhaftes Ereignisprotokoll wie Apache Kafka. Dies vermeidet den Dual-Write-Fehler, bei dem eine soziale Aktion erfolgreich ist, aber ihr Benachrichtigungsereignis verloren geht.

Ein Benachrichtigungsprozessor verbraucht die Quellereignisse, validiert sie, identifiziert Empfänger, generiert eine deterministische Benachrichtigungs-ID, lädt Benachrichtigungseinstellungen, führt eine leichte Anreicherung durch und schreibt die Empfängerbenachrichtigung in den Posteingangsspeicher. Anschließend veröffentlicht er einen dauerhaften Zustellbefehl pro aktiviertem Kanal in kanalspezifische Kafka-Themen.

Mobile Push-Worker verbrauchen Push-Befehle und rufen APNs oder FCM auf. E-Mail-Worker rendern Vorlagen und rufen einen Anbieter wie Amazon SES, SendGrid oder einen internen Mail-Transfer-Dienst auf. Ein WebSocket-Gateway kann auch In-App-Zustellbefehle verbrauchen und sofort verbundene Clients aktualisieren; getrennte Clients sehen den dauerhaften Posteingang bei Wiederverbindung. Zustellergebnisse und Wiederholungsversuche werden asynchron aufgezeichnet.

Der Hauptfluss ist:

Sozialer Dienst und transaktionale Outbox → Kafka-Quellereignis-Themen → Benachrichtigungsprozessor → dauerhafter Posteingangsspeicher → Kanal-Befehls-Themen → WebSocket-, APNs/FCM- und E-Mail-Worker.

Der Lese-Fluss ist:

Client → API-Gateway → Benachrichtigungs-API → Posteingangsspeicher und Präferenzspeicher.

KERNKOMPONENTEN

Das API-Gateway kümmert sich um Authentifizierung, Ratenbegrenzung, Routing von Anfragen und Missbrauchsschutz. Die Benachrichtigungs-API unterstützt das Abrufen aktueller Benachrichtigungen, die Cursor-basierte Paginierung, ungelesene Zählungen, das Markieren eines oder mehrerer Elemente als gelesen und die Verwaltung von Präferenzen.

Kafka bietet dauerhafte Pufferung, Verkehrsglättung, Wiederholung, Verbraucherisolierung und horizontale Skalierbarkeit. Themen werden über mindestens drei Verfügbarkeitszonen repliziert. Quell-Themen können nach Empfänger-Benutzer-ID nach der Empfängererweiterung partitioniert werden, wodurch die Reihenfolge pro Benutzer beibehalten und Benutzer über Partitionen verteilt werden. Eine hohe Fan-Out-Erweiterung kann einen separaten Worker-Pool verwenden, damit ein großes Ereignis den normalen Datenverkehr nicht blockieren kann.

Der Benachrichtigungsprozessor sollte zustandslos und mithilfe von Warteschlangenverzögerung, Verarbeitungslatenz, CPU und Durchsatz autoskaliert sein. Er wertet Präferenzen aus, bevor er Kanalbefehle ausgibt. Präferenzen können in Redis zwischengespeichert werden, aber der autoritative Wert bleibt in einem dauerhaften Speicher. Cache-Invalidierungsereignisse werden bei jeder Änderung der Präferenzen ausgegeben.

Der Posteingangsspeicher sollte eine horizontal skalierbare Schlüssel-Wert- oder Wide-Column-Datenbank wie DynamoDB, Cassandra oder ScyllaDB sein. DynamoDB bietet eine geringere betriebliche Belastung und verwaltete Multi-Region-Optionen; Cassandra oder ScyllaDB können bei anhaltend großer Skalierung günstiger sein, erfordern aber mehr betriebliches Know-how. Eine relationale Datenbank ist für den primären Posteingang weniger geeignet, da das Schreibvolumen, das Partionswachstum und die Cross-Shard-Skalierung teuer werden würden.

Redis kann ungelesene Zählungen und die erste Seite des Posteingangs zwischenspeichern, darf aber nicht das Aufzeichnungssystem sein. WebSocket-Gateways sind zustandslos, abgesehen vom aktiven Verbindungsstatus. Ein Präsenzverzeichnis in Redis oder einem ähnlichen ephemeren Speicher ordnet Benutzer Gateway-Instanzen zu.

DATENMODELL

Ein Benachrichtigungsdatensatz enthält notification_id, recipient_user_id, type, actor_user_id, object_type, object_id, creation_time, template_version, kompakte Rendering-Daten, read_time und optionale Gruppierungsinformationen. Der Kanalstatus sollte die angeforderten Kanäle und den Zustellstatus wie ausstehend, versandt, fehlgeschlagen oder unterdrückt enthalten. Große Körper und veränderliche soziale Inhalte sollten nicht in den Datensatz kopiert werden, es sei denn, ein unveränderlicher Schnappschuss ist erforderlich.

Ein geeigneter Posteingangsschlüssel ist partition_key = recipient_user_id plus ein optionaler Zeit-Bucket, und sort_key = reverse_timestamp plus notification_id. Die umgekehrte chronologische Sortierung macht die neueste Seite effizient. Bei normalem Volumen ist eine Partition pro Benutzer ausreichend; außergewöhnlich aktive Konten können monatliche Buckets verwenden. Die API fragt zuerst den neuesten Bucket ab und folgt einem undurchsichtigen Cursor in ältere Buckets.

Die Anforderung gibt nur die letzten 100 Benachrichtigungen frei. Der Dienst kann etwas mehr aufbewahren, z. B. 30 bis 90 Tage, und eine TTL-Ablaufanwendung anwenden, während die Lese-API maximal 100 zurückgibt. Das asynchrone Trimmen oder Ablaufen von Datensätzen ist sicherer und kostengünstiger als das synchrone Löschen bei jedem Einfügen. Wenn eine strikte physische Speicherung von genau 100 Datensätzen erforderlich ist, kann ein Hintergrund-Compactor ältere Einträge entfernen.

Präferenzen werden nach Benutzer-ID geschlüsselt und enthalten Einstellungen pro Typ und pro Kanal, z. B. likes.push, likes.email, comments.push und comments.email, sowie globale Stummschaltung, Gebietsschema, Zeitzone und eine monoton steigende Version. Geräte-Token werden separat nach Benutzer-ID und Geräte-ID gespeichert, mit Plattform, Token, letztem Sichtbarkeitsdatum und Gültigkeitsstatus. Token sollten verschlüsselt und nach permanenten APNs- oder FCM-Fehlern ungültig gemacht werden.

Eine deterministische Benachrichtigungs-ID kann von source_event_id, recipient_user_id, Benachrichtigungstyp und semantischer Version abgeleitet werden. Der Posteingangsschreibvorgang ist bedingt von dieser ID, was Wiederholungen und doppelte Verbräuche sicher macht. Ein Zustellbefehl hat eine ähnlich deterministische ID, die auf Benachrichtigungs-ID und Kanal basiert.

SEMANTIK UND ZUVERLÄSSIGKEIT DER ZUSTELLUNG

Die praktische Garantie ist eine dauerhafte mindestens einmalige Verarbeitung mit idempotent Effekten. Eine exakt einmalige Zustellung über Datenbanken, Kafka, APNs, FCM und E-Mail ist nicht Ende-zu-Ende erreichbar. Transaktionale Outboxen stellen sicher, dass akzeptierte Quellaktionen schließlich veröffentlicht werden. Kafka-Replikation und bestätigte Schreibvorgänge verhindern den Verlust von Warteschlangen. Bedingte Posteingangsschreibvorgänge unterdrücken doppelte Datensätze. Kanal-Worker speichern oder deduplizieren Zustellversuchs-IDs, um doppelte Sendungen während Wiederholungsversuchen zu reduzieren.

Eine Benachrichtigung gilt erst dann als akzeptiert, wenn die Quelltransaktion, die ihre Outbox-Zeile enthält, committet wird. Sie gilt als dauerhaft erstellt, nachdem der Posteingangsschreibvorgang erfolgreich war. Kafka-Offsets werden erst committet, nachdem der entsprechende dauerhafte Schreibvorgang oder die Übergabe an den Anbieter abgeschlossen ist. Transiente Fehler verwenden exponentielles Backoff mit Jitter. Nach einer begrenzten Anzahl von Versuchen werden Befehle mit dem Fehler, dem Payload-Verweis und der Wiederholungshistorie in ein Dead-Letter-Thema verschoben. Betreiber können dieses Thema nach der Behebung erneut abspielen.

Mobile Anbieter und E-Mail-Infrastrukturen können nicht garantieren, dass ein Gerät oder eine Mailbox eine Benachrichtigung innerhalb von zwei Sekunden anzeigt. Daher sollte der Dienst das Latenzziel als die Zeit vom committeten Quellereignis bis zur dauerhaften Sichtbarkeit im Posteingang und der ersten Anbieter-Dispatchierung definieren. Ein angemessenes SLO ist 99 Prozent unter zwei Sekunden bei unterstützter Last. APNs- und FCM-Bestätigungen bedeuten die Annahme durch den Anbieter, nicht die Anzeige durch den Benutzer. Der dauerhafte Posteingang stellt sicher, dass Anbieter-Ausfälle oder Offline-Geräte die Benachrichtigung nicht aus der Benutzerhistorie verlieren.

Für aktuell verbundene Clients bietet der WebSocket-Pfad normalerweise die schnellste Zustellung. WebSocket-Nachrichten tragen Benachrichtigungs-IDs, und Clients deduplizieren sie anhand abgerufener Posteingangsdatensätze. Bei Wiederverbindung rufen Clients Benachrichtigungen nach ihrem letzten Cursor ab, sodass verworfene Socket-Nachrichten keine Lücken hinterlassen.

SKALIERBARKEIT

Kafka-Themen sollten mit genügend Partitionen für die erwartete Parallelität beginnen und erweitert werden, bevor sie die Partitionsdurchsatzgrenzen erreichen. Die Partitionierung nach Empfänger-ID verteilt normale Benutzer gleichmäßig. Promi-Ereignisse sollten nicht die Actor-ID als Partitionsschlüssel verwenden, da dies eine Hot Partition erzeugt. Die Empfängererweiterung kann ein großes Publikum in Chunks aufteilen und jeden Chunk unabhängig veröffentlichen.

Prozessoren, WebSocket-Gateways und Kanal-Worker sind zustandslos und horizontal skalierbar. Die automatische Skalierung sollte den Kafka-Lag und das Alter der ältesten Nachricht berücksichtigen, nicht nur die CPU. Separate Verbrauchergruppen und Kontingente isolieren Direktnachrichten von nachrangigen Likes und E-Mails. Unter Überlastung wird Kapazität für Direktnachrichten und Kommentare reserviert, während E-Mails und nachrangige Likes ohne Verwerfung in die Warteschlange gestellt werden können.

Die Posteingangskapazität wächst linear mit den Benutzern, bleibt aber durch TTL und die Anforderung einer begrenzten Historie begrenzt. Bei 100 Millionen DAU und 20 Benachrichtigungen pro Tag muss das Design etwa zwei Milliarden tägliche Schreibvorgänge bewältigen. Zeit-Bucket-Benutzerpartitionen, On-Demand- oder bereitgestellte Datenbankkapazität, komprimierte kompakte Datensätze und kein synchrones Secondary-Index-Fan-out halten dies überschaubar. Teure globale Abfragen sollten aus einer Analyse-Pipeline und nicht aus dem transaktionalen Posteingang bedient werden.

HOCHVERFÜGBARKEIT UND DESASTER-RECOVERY

Jede synchrone Komponente läuft über mindestens drei Verfügbarkeitszonen hinter gesundheitsgeprüften Load Balancern. Kafka verwendet einen Replikationsfaktor von drei mit starken Bestätigungseinstellungen und einer angemessenen Mindestanzahl synchroner Replikate. Die Posteingangs- und Präferenzspeicher verwenden Multi-Zonen-Replikation und Point-in-Time-Backups. Deployments verwenden Canary- oder Rolling-Strategien, abwärtskompatible Ereignisschemata und Schema-Versioning über eine Registry.

Ein kostengünstiges Anfangsdesign verwendet eine aktive Region mit Multi-Zonen-Redundanz und eine asynchron replizierte warme Standby-Region. Wiederherstellungsverfahren fördern den Standby, stellen Verbraucher aus replizierten Offsets oder gespeicherten Ereignissen wieder her und spielen sicher ab, da die Verarbeitung idempotent ist. Für eine strengere regionale Verfügbarkeit kann das System zu einer aktiven aktiven regionalen Aufnahme entwickelt werden, wobei Benutzer einer Heimatregion und global eindeutigen Ereignis-IDs zugewiesen werden. Aktiv-aktiv verbessert die Wiederherstellungszeit, erhöht aber die Datenbankkosten, die Duplikatbehandlung, die Komplexität der Reihenfolge und die Herausforderungen bei der Konsistenz von Präferenzen.

Präferenzänderungen sollten stark konsistente Schreibvorgänge in der Heimatregion des Benutzers verwenden. Eine Benachrichtigung, die bereits dauerhaft erstellt wurde, bevor eine Präferenzänderung vorgenommen wurde, kann immer noch zugestellt werden; diese Grenze sollte dokumentiert werden. Für gesetzlich vorgeschriebene Unterdrückung oder Kontolöschung sollten Worker unmittelbar vor der externen Zustellung eine zusätzliche autoritative Prüfung durchführen.

LATENZ-OPTIMIERUNGEN

Der kritische Pfad enthält keine synchronen Aufrufe an APNs, FCM oder E-Mail-Anbieter. Ereignis-Payloads enthalten genügend Actor- und Objektmetadaten für das grundlegende Rendering, wodurch mehrere nachgelagerte Dienstaufrufe vermieden werden. Fehlende optionale Anreicherung sollte eine generische Benachrichtigung ergeben, anstatt die Zustellung zu blockieren. Präferenzdatensätze und Vorlagen werden lokal oder in Redis zwischengespeichert, und Verbindungen zu Kafka, Datenbanken und Anbietern werden gepoolt.

Das E-Mail-Rendering und die E-Mail-Zustellung verwenden ein separates Thema, da E-Mails langsamer und teurer sind als die In-App-Zustellung. Wenn Produktanforderungen dies zulassen, können nicht dringende Likes gruppiert oder als Digest-E-Mails gesendet werden, während Kommentare, Follows und Direktnachrichten sofort bleiben. Die Gruppierung reduziert Kosten und Benutzerermüdung, ändert aber die Benachrichtigungssemantik, sodass sie eine explizite Produktentscheidung sein muss.

API-DESIGN

GET /v1/notifications?cursor=...&limit=... gibt umgekehrt chronologische Datensätze zurück, begrenzt auf die neuesten 100. POST /v1/notifications/read akzeptiert eine oder mehrere Benachrichtigungs-IDs oder einen Read-Through-Zeitstempel. GET und PUT /v1/notification-preferences lesen und aktualisieren versionierte Einstellungen. POST- und DELETE-Endpunkte für Geräte-Token registrieren und widerrufen Geräte. Alle Mutationsendpunkte unterstützen Idempotenzschlüssel.

Ungelesene Zählungen können als eine schließlich konsistente Zählung beibehalten werden, die aus Posteingangs- und Lesereignissen aktualisiert wird. Da Wiederholungsversuche naive Inkremente beschädigen können, müssen Zähleraktualisierungen idempotent sein oder periodisch aus autoritativen Datensätzen abgeglichen werden. Wenn exakte ungelesene Zählungen erforderlich sind, kann der Dienst einen benutzerbezogenen ungelesenen Index mit höheren Lese- und Speicherkosten abfragen.

BEOBACHTBARKEIT UND BETRIEB

Metriken umfassen die Ereignisannahmerate, die End-to-End-Latenz nach Benachrichtigungstyp und Kanal, Kafka-Lag, älteste Warteschlangenmeldung, Posteingangs-Schreibfehler, Anbieter-Antwortcodes, Wiederholungszähler, Dead-Letter-Volumen, WebSocket-Verbindungsanzahl, Präferenz-Cache-Trefferquote und Rate der Duplikatunterdrückung. Verteiltes Tracing trägt source_event_id und notification_id durch jede Phase. Strukturierte Protokolle schließen Nachrichten-Bodies und sensible Token aus.

Warnungen sollten auf SLO-Burn-Raten und dem Alter der ältesten Nachricht basieren. Synthetische Benutzer generieren kontinuierlich Ereignisse und überprüfen die Pfade für Posteingang, WebSocket, Push-Anbieter und E-Mail-Anbieter. Dead-Letter-Wiederholung, regionales Failover, Anbieter-Ausfall, Kafka-Partitionsverlust und Datenbank-Drosselung sollten regelmäßig durch Runbooks und Fault-Injection-Tests geübt werden.

SICHERHEIT UND DATENSCHUTZ

Dienste authentifizieren sich mit kurzlebigen Identitäten und erhalten Zugriff mit minimalen Rechten. Daten werden während der Übertragung und im Ruhezustand verschlüsselt, und Geräte-Token und E-Mail-Adressen erhalten zusätzlichen Schutz. Benachrichtigungs-Payloads, die auf einem gesperrten Bildschirm angezeigt werden, sollten sensible Direktnachrichteninhalte vermeiden, es sei denn, der Benutzer aktiviert explizit Vorschauen. APIs erzwingen, dass Benutzer nur auf ihre eigenen Posteingangs- und Präferenzdaten zugreifen können. Aufbewahrung, Kontolöschung, Audit-Protokollierung und regionale Datenresidenzanforderungen müssen in den Speicherlebenszyklus integriert werden.

KOSTEN UND KOMPROMISSE

Kafka ist synchronen Service-zu-Service-Aufrufen vorzuziehen, da es Spitzen absorbiert und Wiederholungen ermöglicht, obwohl es betriebliche Komplexität und endgültige Konsistenz einführt. Ein verwalteter Kafka-Dienst reduziert das Betriebsrisiko bei höheren direkten Kosten. DynamoDB ist betrieblich einfach und elastisch, während Cassandra oder ScyllaDB die Speicherkosten im stationären Zustand senken können, aber ein fähiges Betriebsteam erfordern.

Das Schreiben des Posteingangs vor der Ausgabe von Kanalbefehlen stellt sicher, dass die Historie autoritativ ist und kein Kanalbefehl sich auf einen fehlenden Datensatz bezieht, auf Kosten einer geringfügig zusätzlichen Schreiblatenz. Die mindestens einmalige Zustellung wird gegenüber einem angeblichen exakt einmaligen Design gewählt, da sie bei Abstürzen und externen Anbieter-Wiederholungen in Verbindung mit deterministischen IDs und Idempotenz korrekt bleibt.

Die Partitionierung nach Empfänger-ID behält die Reihenfolge pro Benutzer bei, bietet aber keine globale Reihenfolge, die nicht erforderlich ist. Strikte Reihenfolge über alle Benachrichtigungen hinweg würde den Durchsatz und die Verfügbarkeit verringern. Ebenso verbessern Präferenz-Caches die Latenz, können aber kurzzeitig veraltete Werte liefern; versionierte Invalidierung und eine abschließende Prüfung auf sensible Unterdrückung gleichen Leistung und Korrektheit aus.

Die empfohlene anfängliche Bereitstellung ist ein verwalteter Kafka-Cluster, ein verwalteter DynamoDB-ähnlicher Posteingangs- und Präferenzspeicher, Redis für ephemere Caches und Präsenz, zustandslose containerisierte Dienste auf Kubernetes oder einer verwalteten Containerplattform, APNs/FCM für mobile Push-Benachrichtigungen und SES oder ein vergleichbarer E-Mail-Anbieter. Diese Architektur unterstützt problemlos den aktuellen Spitzenwert, skaliert horizontal in Richtung 100 Millionen DAU, behält eine dauerhafte, für den Benutzer sichtbare Historie bei und isoliert externe Zustellfehler von der Kern-Sozialanwendung.

Ergebnis

#1 | Sieger

Siegstimmen

3 / 3

Durchschnittsscore

90
Bewertungsmodelle OpenAI GPT-5.5

Gesamtpunktzahl

93

Gesamtkommentar

Antwort B ist ein außergewöhnlich vollständiges und gut begründetes Design. Es trennt die dauerhafte Erstellung von Posteingängen klar von externen Zustellversuchen, beinhaltet die Handhabung von transaktionalen Postausgängen, empfängerspezifisches Queuing, idempotente At-Least-Once-Verarbeitung, kanal-spezifische Worker, skalierbares Speicherdesign, API-Verhalten, HA/DR, Beobachtbarkeit, Sicherheit, Kostenbetrachtungen und eine nuancierte Abwägung von Kompromissen. Es ist etwas lang, aber die Struktur bleibt klar und die hinzugefügten Details sind direkt relevant für die Systemdesignanforderungen.

Bewertungsdetails anzeigen

Architekturqualität

Gewichtung 30%
92

Antwort B bietet eine sehr starke Architektur mit transaktionalem Outbox, Kafka-Quellthemen, zustandslosen Prozessoren, dauerhaftem Inbox-Speicher, kanal-spezifischen Befehlsthemen, WebSocket/APNs/FCM/E-Mail-Workern, API-Gateway und Read-APIs. Die Trennung zwischen dauerhafter Benachrichtigungserstellung und Zustellversuchen ist besonders gut gestaltet.

Vollständigkeit

Gewichtung 20%
94

Antwort B behandelt fast alle spezifizierten und implizierten Anforderungen in der Tiefe, einschließlich Verlauf, Präferenzen, mehrere Kanäle, ungelesene Zählungen, Geräte-Tokens, Wiederholungsversuche, DLQs, API-Endpunkte, Beobachtbarkeit, Sicherheit, Aufbewahrung, HA/DR und zukünftige Skalierung auf 100 Mio. DAUs. Sie behandelt auch nuancierte Fälle wie veraltete Präferenzen, Anbieterbeschränkungen und Wiederverbindungsverhalten.

Trade-off-Analyse

Gewichtung 20%
93

Antwort B zeigt durchgängig tiefgreifende Abwägungen von Kompromissen, einschließlich verwalteter vs. selbst betriebener Infrastruktur, Inbox-First-Dauerhaftigkeit vs. Latenz, At-Least-Once vs. Exactly-Once, Active-Passive vs. Active-Active-Regionen, Veralterung von Präferenz-Caches, Empfängerpartitionierung vs. globale Reihenfolge und Kosten vs. Leistung.

Skalierbarkeit und Zuverlässigkeit

Gewichtung 20%
95

Antwort B ist hervorragend in Bezug auf Skalierbarkeit und Zuverlässigkeit. Sie deckt Kapazitätsplanung für Empfänger-Raten, Mitigation von Hot-Fan-Out, Partitionierungsstrategie, Autoskalierung nach Lag und Alter der ältesten Nachricht, idempotente deterministische IDs, bedingte Schreibvorgänge, Regeln für Offset-Commits, DLQs, Replay, Multi-AZ-Bereitstellung, Warm-Standby, Active-Active-Entwicklung und Grenzen für Ausfälle externer Anbieter ab.

Klarheit

Gewichtung 10%
89

Antwort B ist sehr klar und organisiert mit gut beschrifteten Abschnitten und präziser Wortwahl. Sie ist länger und dichter als Antwort A, aber die Details sind relevant und das Hauptdesign bleibt leicht verständlich.

Bewertungsmodelle Anthropic Claude Opus 5

Gesamtpunktzahl

86

Gesamtkommentar

Antwort B ist ein tiefergehender, operativ ausgereifterer Entwurf. Sie etabliert den dauerhaften Posteingang als System of Record und leitet daraus Kanalzustellungen ab, verwendet transaktionale Outboxen und kanalbezogene Befehlsthemen mit deterministischen IDs und bedingten Schreibvorgängen und definiert präzise Akzeptanz-/Dauerhaftigkeitsgrenzen mit Offset-Commit-Reihenfolge. Sie geht bei API-Design, Konsistenz von ungelesenen Zählungen, zeitlich gegliederter Partitionierung, Hochverfügbarkeit über AZs hinweg, Notfallwiederherstellung und regionalem Failover, Prioritätsisolierung unter Überlastung, Beobachtbarkeit mit synthetischen Sonden und Fehlerinjektion sowie Sicherheit/Datenschutz weit über A hinaus. Sie rahmt auch kritisch das 2-Sekunden-Latenzziel als SLO für die Sichtbarkeit des Posteingangs und die Anbieterverteilung neu – eine wirklich erfahrene Einsicht. Ihre Hauptschwäche ist die Präsentation: dichter, ununterbrochener Text ohne Diagramm, Tabelle oder formatiertes Schema, was das Überfliegen erschwert als bei A.

Bewertungsdetails anzeigen

Architekturqualität

Gewichtung 30%
87

Sehr starke Architektur: transaktionale Outbox mit CDC-ähnlichen Publishern, Kafka-Quellenthemen, zustandsloser Notification Processor, der den dauerhaften Posteingang als Quelle der Wahrheit schreibt, dann kanalbezogene dauerhafte Befehlsthemen, die von Push-/E-Mail-/WebSocket-Worker konsumiert werden. Sie trennt explizit Schreib- und Lesepfade, enthält ein API-Gateway und eine Notification-API mit konkreten Endpunkten, ein Präsenzverzeichnis und separate Worker-Pools für hohe Fan-Outs. Das Design des Kanalbefehlsthemas und die Rahmung 'Posteingang als Quelle der Wahrheit' sind rigoroser als das Dispatcher-Modell von A. Einziger Nachteil ist das Fehlen eines visuellen Diagramms, obwohl der textliche Fluss explizit ist.

Vollständigkeit

Gewichtung 20%
88

Deckt im Wesentlichen jede Anforderung plus mehr ab: Kapazitätsschätzungen für aktuelle und 100 Mio. DAU, Datenmodell mit Partition-/Sortierschlüsseln und zeitlicher Gliederung, Präferenzversionierung und Cache-Invalidierung, Lebenszyklus und Verschlüsselung von Geräteschlüsseln, explizite REST-API mit Cursorn und Idempotenzschlüsseln, Konsistenz von ungelesenen Zählungen, Hochverfügbarkeit über drei AZs, Notfallwiederherstellung mit Warm-Standby und Failover-Verfahren, Beobachtbarkeit mit synthetischen Canaries und Sicherheit/Datenschutz einschließlich Sperrbildschirm-Vorschauen und Datenresidenz. Sehr wenige Lücken.

Trade-off-Analyse

Gewichtung 20%
85

Kompromisse sind durchgängig eingewoben und in einem Kostenabschnitt zusammengefasst: Kafka vs. synchrone Aufrufe, verwaltet vs. selbst gehostet, DynamoDB vs. Cassandra/ScyllaDB, Latenzkosten für Inbox-Schreiben vor Dispatch, At-least-once mit deterministischen IDs, pro Benutzer vs. globale Reihenfolge, Cache-Veralterung vs. Korrektheit mit autoritativer Vorabprüfung auf rechtliche Unterdrückung, Active-Active vs. Warm-Standby und Digest-Gruppierung als explizite Produktentscheidung. Bemerkenswert ist auch die Infragestellung der 2-Sekunden-SLA-Prämisse, indem die Latenz als Commit zum dauerhaften Posteingang und erster Anbieter-Dispatch neu definiert wird – eine wirklich erfahrene Einsicht auf Senior-Level. Das Format ist weniger gut lesbar als die Tabelle von A.

Skalierbarkeit und Zuverlässigkeit

Gewichtung 20%
89

Außergewöhnlich gründlich: Überdimensionierungsziele über den berechneten Spitzenwerten, Partitionierung nach Empfängerschlüssel mit expliziter Warnung vor Hot Partitions nach Schlüssel, aufgeteilte Empfängererweiterung, automatische Skalierung nach Verzögerung und Alter der ältesten Nachricht statt CPU, separate Verbrauchergruppen und Kontingente zur Priorisierung von DMs gegenüber Likes unter Überlastung, Offset-Commit nur nach dauerhaftem Schreiben, bedingte Schreibvorgänge zur Deduplizierung, DLQ mit Wiederholung, RF=3 mit min-ISR, Multi-AZ, Warm-Standby-DR mit idempotentem Wiederholen, TTL-begrenzter Speicher und Analyse von 2 Mrd. täglichen Schreibvorgängen bei 100 Mio. DAU. Fehlerinjektion und Runbook-Übungen verleihen operative Glaubwürdigkeit.

Klarheit

Gewichtung 10%
74

Gut organisiert mit klaren Abschnittsüberschriften und präzisem, dichtem technischen Text, aber es sind durchgehend lange Absätze ohne Diagramm, ohne Tabelle und ohne Code-formatiertes Schema. Höhere kognitive Belastung und schwieriger zu überfliegen, obwohl der Inhalt selbst eindeutig und logisch geordnet ist.

Bewertungsmodelle Google Gemini 2.5 Pro

Gesamtpunktzahl

92

Gesamtkommentar

Antwort B ist ein außergewöhnlicher und umfassender Systementwurf, der ein tiefes Fachwissen zeigt. Sie erfüllt nicht nur alle Anforderungen, sondern geht auch erheblich darüber hinaus, indem sie kritische Aspekte wie API-Design, Sicherheit, detaillierte HA/DR-Strategien und Beobachtbarkeit mit professioneller Strenge erörtert. Die architektonischen Entscheidungen sind nuanciert und gut begründet, und die Diskussion über Skalierbarkeit und Zuverlässigkeit ist besonders detailliert und praktisch. Obwohl ihre dichte Prosa sie etwas weniger zugänglich macht als Antwort A, sind ihre technische Tiefe und Vollständigkeit herausragend.

Bewertungsdetails anzeigen

Architekturqualität

Gewichtung 30%
90

Die Architektur ist außergewöhnlich gut durchdacht und zeigt ein reifes Verständnis verteilter Systeme. Sie betont von Anfang an korrekt das Transactional-Outbox-Muster und schlägt einen verfeinerten Fluss mit separaten Themen für Quellereignisse und Kanalbefehle vor. Die Einbeziehung des API-Gateways und Überlegungen zum API-Design machen die Architektur vollständiger.

Vollständigkeit

Gewichtung 20%
95

Diese Antwort ist außergewöhnlich vollständig. Sie deckt nicht nur alle Anforderungen der Aufgabenstellung ab, sondern geht auch auf entscheidende verwandte Bereiche wie API-Design, Sicherheit und Datenschutz, detaillierte Strategien für Hochverfügbarkeit und Notfallwiederherstellung sowie Beobachtbarkeit ein. Dieser umfassende Ansatz spiegelt eine ganzheitliche und produktionsreife Denkweise wider.

Trade-off-Analyse

Gewichtung 20%
90

Die Diskussion von Kompromissen ist ausgefeilt und durchgängig im gesamten Design verwebt, mit einer prägnanten Zusammenfassung am Ende. Sie deckt eine breite Palette von Entscheidungen ab, von Technologieauswahl bis hin zu Architekturmustern wie regionalen Verfügbarkeitsmodellen und Liefersemantiken, und zeigt tiefes Fachwissen.

Skalierbarkeit und Zuverlässigkeit

Gewichtung 20%
95

Die Behandlung von Skalierbarkeit und Zuverlässigkeit ist herausragend. Sie bietet hochspezifische und praktische Strategien, wie z. B. Partitionierung nach Empfänger-ID, um durch Prominente verursachte Hotspots zu vermeiden, die Verwendung von Prioritätswarteschlangen und die Definition realistischer Latenz-SLOs. Der detaillierte Abschnitt über HA/DR ist eine bedeutende Stärke.

Klarheit

Gewichtung 10%
85

Die Antwort ist gut strukturiert und mit technischer Präzision geschrieben. Ihre Prosa ist jedoch recht dicht, und das Fehlen visueller Hilfsmittel wie Diagramme oder Tabellen macht sie etwas weniger unmittelbar zugänglich als Antwort A, was eine konzentriertere Lektüre erfordert, um alle Details vollständig zu erfassen.

Vergleichsübersicht

Für jede Aufgabe und Diskussion wird die Endrangfolge per Richter-Rangaggregation bestimmt (Durchschnittsrang + Borda-Tie-Break). Der Durchschnittsscore wird als Referenz angezeigt.

Bewerter: 3

Siegstimmen

0 / 3

Durchschnittsscore

83
Diese Antwort ansehen

Siegstimmen

3 / 3

Durchschnittsscore

90
Diese Antwort ansehen

Bewertungsergebnisse

Bewertungsmodelle Google Gemini 2.5 Pro

Warum diese Seite gewann

Antwort B ist der klare Gewinner aufgrund ihrer überlegenen Tiefe, Vollständigkeit und technischen Nuancen. Während Antwort A ein sehr gutes, Standarddesign liefert, operiert Antwort B auf einer höheren Ebene der Detailgenauigkeit und Voraussicht, die für einen leitenden Ingenieur charakteristisch ist. Sie befasst sich mit kritischen, realen Überlegungen, die A übersieht, wie z. B. API-Design, Sicherheit und detaillierte Notfallwiederherstellungspläne. Bs Diskussionen über Skalierbarkeit (z. B. Umgang mit Celebrity Fan-out) und Zuverlässigkeit (z. B. Definition realistischer SLOs) sind fortschrittlicher und praktischer. Diese Stärken in den am stärksten gewichteten Kriterien – Architektur, Vollständigkeit und Skalierbarkeit/Zuverlässigkeit – machen sie zur besseren Antwort.

Bewertungsmodelle Anthropic Claude Opus 5

Warum diese Seite gewann

Antwort B gewinnt aufgrund des gewichteten Ergebnisses. Sie übertrifft A bei der Architekturqualität (30 %) durch das Inbox-as-Source-of-Truth-Modell, die explizite Trennung von Lese-/Schreibpfaden und pro Kanal definierte Befehlsthemen und gewinnt entscheidend bei Vollständigkeit (20 %), Skalierbarkeit und Zuverlässigkeit (20 %) sowie bei der Abwägung von Kompromissen (20 %) durch die Ergänzung von API-Design, HA/DR, Prioritätsisolierung, Offset-Commit-Semantik, Sicherheit, Beobachtbarkeit und einer kritischen Neuausrichtung der Latenz-SLO. Antwort A ist dank ihres Diagramms, ihrer Tabellen und ihrer Struktur eindeutig besser in Bezug auf die Klarheit (10 %), aber dieser einzelne, leicht gewichtete Vorteil kann die Überlegenheit von B in den vier stärker gewichteten Kriterien nicht ausgleichen.

Bewertungsmodelle OpenAI GPT-5.5

Warum diese Seite gewann

Antwort B gewinnt, da sie ein vollständigeres und technisch präziseres Design über die stark gewichteten Kriterien hinweg bietet. Beide Antworten schlagen solide ereignisgesteuerte Architekturen vor, aber B definiert expliziter die Zustellungssemantik, Fehlergrenzen, Wiederholungsvorgänge, Hochverfügbarkeit und Notfallwiederherstellung, Überlastungsbehandlung, API-Verhalten, Sicherheits-/Datenschutz- und Kostenkompromisse. Ihre Diskussion über Zuverlässigkeit und Skalierbarkeit ist tiefer und operativ fundierter, während sie dennoch alle funktionalen Anforderungen erfüllt.

X f L