Orivel Orivel
Menü öffnen

Entwerfen Sie einen URL-Shortener für 10.000 Anfragen pro Sekunde

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

Entwerfen Sie einen URL-Kürzungsdienst (ähnlich im Sinn eines "Tiny-Link"-Produkts), der zuverlässig in großem Maßstab betrieben werden kann. Präsentieren Sie Ihre Antwort als ein strukturiertes System-Design-Dokument.

Funktionale Anforderungen:

  • Benutzer übermitteln eine lange URL und erhalten einen kurzen Link (z. B. ein 7-stelliges Codewort).
  • Jeder, der einen Kurzlink besucht, wird zur ursprünglichen URL weitergeleitet.
  • Optionale benutzerdefinierte Aliase, die von Benutzern angefordert werden, müssen bei V...
Mehr anzeigen

Entwerfen Sie einen URL-Kürzungsdienst (ähnlich im Sinn eines "Tiny-Link"-Produkts), der zuverlässig in großem Maßstab betrieben werden kann. Präsentieren Sie Ihre Antwort als ein strukturiertes System-Design-Dokument.

Funktionale Anforderungen:

  • Benutzer übermitteln eine lange URL und erhalten einen kurzen Link (z. B. ein 7-stelliges Codewort).
  • Jeder, der einen Kurzlink besucht, wird zur ursprünglichen URL weitergeleitet.
  • Optionale benutzerdefinierte Aliase, die von Benutzern angefordert werden, müssen bei Verfügbarkeit berücksichtigt werden.
  • Grundlegende Klick-Analytik: Gesamtanzahl der Klicks pro Kurzlink.

Nicht-funktionale Vorgaben (entwerfen Sie explizit anhand dieser Zahlen):

  • Spitzentraffic: 10.000 Redirect-Anfragen pro Sekunde, mit einem Lese:Schreib-Verhältnis von ungefähr 100:1.
  • Redirect-Latenzziel: p99 unter 50 ms, serverseitig gemessen.
  • Insgesamt gespeicherte Links über 5 Jahre: etwa 30 Milliarden.
  • Redirect-Verfügbarkeitsziel: 99,99 % monatlich.
  • Short-Codes dürfen nicht massenhaft erratbar sein (vermeiden Sie einfache sequenzielle Offenlegung).

Ihr Design-Dokument sollte Folgendes abdecken, und für jede bedeutende Entscheidung erklären Sie den Kompromiss, den Sie eingehen:

  1. High-Level-Architektur und Request-Flow für sowohl den Schreibpfad (Erstellen) als auch den Lese-/Redirect-Pfad.
  2. Strategie zur Erzeugung von Short-Codes, einschließlich wie Sie Eindeutigkeit garantieren und Kollisionen bei benutzerdefinierten Aliasen behandeln.
  3. Datenmodell und Auswahl der(n) Datenspeicher(s) mit einer groben Kapazitäts-/Speicherschätzung, die die Wahl rechtfertigt.
  4. Caching-Strategie und wie Sie „heiße“ Links schnell halten, einschließlich Cache-Invalidierung und was bei einem Cache-Miss passiert.
  5. Skalierungsstrategie: wie der Lese-Pfad skaliert, um Latenz- und Durchsatzziele zu erreichen, und wie Sie Daten partitionieren/sharden.
  6. Zuverlässigkeit und Fehlerbehandlung: was passiert, wenn ein Datenspeicherknoten, Cache oder eine Region ausfällt; wie Sie das Verfügbarkeitsziel erreichen.
  7. Wie Klick-Analysen gesammelt werden, ohne den schnellen Redirect-Hot-Pfad zu verlangsamen.

Nennen Sie alle Annahmen, die Sie treffen. Halten Sie das Dokument fokussiert und technisch konkret statt allgemein.

Bewertungsrichtlinie

Eine starke Antwort geht direkt auf jede nummerierte Anforderung ein und verknüpft Entscheidungen mit den genannten Vorgaben (10K RPS, Lese:Schreib-Verhältnis 100:1, p99 unter 50 ms, 30 Milliarden Links, 99,99 % Verfügbarkeit, nicht-erratbare Codes) statt allgemeiner Systemdesign-Floskeln.

Belohnt werden Antworten, die: eine geeignete Short-Code-Schema wählen und korrekt erklären, wie Eindeutigkeit und Kollisionen bei benutzerdefinierten Aliasen gehandhabt werden; die Datenspeicher-Wahl mit einer plausiblen Speich...

Mehr anzeigen

Eine starke Antwort geht direkt auf jede nummerierte Anforderung ein und verknüpft Entscheidungen mit den genannten Vorgaben (10K RPS, Lese:Schreib-Verhältnis 100:1, p99 unter 50 ms, 30 Milliarden Links, 99,99 % Verfügbarkeit, nicht-erratbare Codes) statt allgemeiner Systemdesign-Floskeln.

Belohnt werden Antworten, die: eine geeignete Short-Code-Schema wählen und korrekt erklären, wie Eindeutigkeit und Kollisionen bei benutzerdefinierten Aliasen gehandhabt werden; die Datenspeicher-Wahl mit einer plausiblen Speicher-/Kapazitätsschätzung begründen, die aus den gegebenen Zahlen abgeleitet ist; eine kohärente Caching-Schicht mit explizitem Cache-Miss- und Invalidierungsverhalten beschreiben; Sharding/Partitionierung erklären und wie der Lese-Pfad Latenz und Durchsatz erfüllt; und konkrete Fehlerbehandlung (Knoten-, Cache- und Regionsausfälle) beschreiben, die glaubwürdig das 99,99 %-Ziel unterstützt. Analytik sollte asynchron gehandhabt werden, damit der Redirect-Pfad schnell bleibt.

Wert legen auf klare Abwägungen: Eine gute Antwort benennt die Nachteile jeder größeren Wahl (z. B. Konsistenz vs. Latenz, Speicherkosten vs. Lesegeschwindigkeit, Erratbarkeit vs. Einfachheit) statt Entscheidungen als kostenlose Vorteile darzustellen. Bestrafen Sie vage Aussagen, fehlende Anforderungen, Zahlen, die den Vorgaben widersprechen, intern inkonsistente Architekturen oder unbegründete Behauptungen. Ordentliche Struktur und explizit genannte, vernünftige Annahmen werden belohnt; übermäßige Länge ohne Substanz nicht.

Antworten

Antwort A: OpenAI GPT-5.6

Systemdesign: skalierbarer URL-Shortener

Annahmen

  1. Der Weiterleitungsverkehr erreicht Spitzen von 10.000 Anfragen pro Sekunde. Ein nominales Lese-Schreib-Verhältnis von 100:1 impliziert bei diesem Spitzenwert etwa 100 Erstellungen pro Sekunde.
  2. Dreißig Milliarden Links in fünf Jahren erfordern im Durchschnitt etwa 190 Erstellungen pro Sekunde. Daher werden Speicher und Schreibpfad für mindestens 1.000 Erstellungen pro Sekunde ausgelegt, um diese Zahl zu erreichen und Spitzen abzufangen.
  3. Links sind standardmäßig unveränderlich. Wenn Löschung oder Zielbearbeitung später unterstützt wird, erfolgt dies über...
Vollständige Antwort anzeigen

Systemdesign: skalierbarer URL-Shortener

Annahmen

  1. Der Weiterleitungsverkehr erreicht Spitzen von 10.000 Anfragen pro Sekunde. Ein nominales Lese-Schreib-Verhältnis von 100:1 impliziert bei diesem Spitzenwert etwa 100 Erstellungen pro Sekunde.

  2. Dreißig Milliarden Links in fünf Jahren erfordern im Durchschnitt etwa 190 Erstellungen pro Sekunde. Daher werden Speicher und Schreibpfad für mindestens 1.000 Erstellungen pro Sekunde ausgelegt, um diese Zahl zu erreichen und Spitzen abzufangen.

  3. Links sind standardmäßig unveränderlich. Wenn Löschung oder Zielbearbeitung später unterstützt wird, erfolgt dies über explizite Versionierung und Cache-Invalidierung.

  4. Grundlegende Analysen können letztendlich konsistent sein und während katastrophaler Ausfälle eine sehr geringe Anzahl von Ereignissen verlieren. Die Korrektheit der Weiterleitung hängt nicht von den Analysen ab.

  5. Weiterleitungsantworten verwenden HTTP 302 oder 307 anstelle von permanenten 301-Weiterleitungen, um die operative Kontrolle zu erhalten und die Sichtbarkeit der Analysen zu verbessern.

  6. Der Dienst läuft aktiv-aktiv in mindestens drei geografischen Regionen und verwendet eine global replizierte Link-Datenbank.

  7. Architekturübersicht

Komponenten sind globale DNS- oder Anycast-Weiterleitung, regionale Lastausgleichsmechanismen, zustandslose Weiterleitungsdienste, zustandslose Erstellungsdienste, lokale In-Prozess-Caches, regionale verteilte Caches, eine partitionierte Link-Datenbank, ein dauerhafter Ereignisstrom sowie Analyseprozessoren und -speicher.

Erstellungspfad

  1. Ein Client sendet die lange URL und optional einen benutzerdefinierten Alias an die nächstgelegene gesunde Region.
  2. Die API authentifiziert oder begrenzt die Anfragen des Aufrufers, validiert die URL-Syntax, begrenzt die URL-Länge, erlaubt nur unterstützte Schemata wie HTTP und HTTPS und prüft reservierte Aliase.
  3. Für einen automatisch generierten Link erstellt der Dienst einen kryptografisch zufälligen Code. Für einen benutzerdefinierten Alias normalisiert er den Alias gemäß einer dokumentierten, Groß-/Kleinschreibung beachtenden oder ignorierenden Richtlinie.
  4. Der Erstellungsdienst führt eine bedingte Einfügung in die autoritative Datenbank durch: Einfügen nur, wenn der Code oder Alias noch nicht existiert.
  5. Bei einer zufälligen Kollision generiert er einen weiteren Code und versucht es erneut. Bei einer Kollision mit einem benutzerdefinierten Alias gibt er HTTP 409 zurück, ohne den angeforderten Alias stillschweigend zu ändern.
  6. Nachdem die Datenbank den Schreibvorgang bestätigt hat, fügt der Dienst die neue Zuordnung in den lokalen regionalen Cache ein und sendet eine Cache-Füll- oder Invalidierungsnachricht an andere Regionen.
  7. Er gibt die Kurz-URL zurück. Ein Anforderungs-Idempotenzschlüssel kann wiederholte Client-Anfragen demselben Ergebnis zuordnen.

Der Schreibvorgang wird erst nach einem Quorum- oder Konsens-Commit bestätigt. Dies erhöht die Latenz bei übergreifenden Zonen und, je nach Datenbankkonfiguration, übergreifenden Regionen, schafft aber eine autoritative globale Eindeutigkeitsgarantie. Die Erstellung ist weitaus weniger latenzempfindlich als der Weiterleitungsverkehr.

Weiterleitungspfad

  1. Die globale Weiterleitung leitet die Anfrage an die nächstgelegene gesunde Region weiter.
  2. Der Weiterleitungsdienst validiert und extrahiert den Code.
  3. Er prüft einen kleinen In-Prozess-Cache. Wenn nicht vorhanden, prüft er den regionalen verteilten Cache.
  4. Bei einem Cache-Miss führt er eine Punktabfrage in einer lokalen Datenbankreplik durch, wobei der Code als Primärschlüssel verwendet wird.
  5. Wenn gefunden und aktiv, füllt er beide Cache-Ebenen, sendet asynchron ein Klickereignis und gibt sofort eine 302- oder 307-Antwort mit dem Ziel zurück.
  6. Wenn nicht gefunden, gibt er 404 zurück. Negative Ergebnisse werden nur kurzzeitig zwischengespeichert.

Der Weiterleitungspfad hat keine synchrone Analyseoperation und unter normalen Bedingungen keinen übergreifenden Netzwerk-Hop. Zustandslose Dienste skalieren horizontal hinter regionalen Lastausgleichsmechanismen.

  1. Generierung und Eindeutigkeit von Kurzcodes

Ein siebenstelliger Base62-Raum enthält 62^7, etwa 3,52 Billionen, Werte und kann technisch 30 Milliarden Links speichern. Bei 30 Milliarden gespeicherten Links sind jedoch nur etwa 0,85 Prozent dieses Namensraums belegt. Ein zufälliger Massenscanner würde daher etwa einen gültigen Link pro 117 Vermutungen entdecken, was nicht die Anforderung erfüllt, dass Codes schwer zu erraten sind.

Der Standardcode verwendet daher 11 URL-sichere Base62-Zeichen, die aus einer kryptografisch sicheren Zufallsquelle generiert werden. Dies bietet etwa 65,5 Bit und 5,2 × 10^19 Möglichkeiten. Bei 30 Milliarden aktiven Links gelingt eine zufällige Vermutung mit einer Wahrscheinlichkeit von etwa 5,8 × 10^-10. Ratenbegrenzung und Missbrauchserkennung schränken die Enumeration weiter ein. Der Kompromiss ist ein vier Zeichen längerer Link. Siebenstellige Aliase können weiterhin erlaubt sein, wenn sie ausdrücklich von Benutzern gewählt werden, aber sie erhalten nicht die gleiche Garantie der Nicht-Enumerierbarkeit.

Die Zufallsgenerierung vermeidet die Offenlegung der Erstellungsreihenfolge und verteilt die Schlüssel gleichmäßig. Eine bedingte Primärschlüsseleinfügung ist die endgültige Eindeutigkeitsautorität. Geburtstags-Kollisionen über die gesamte Historie hinweg sind in einem Zufallssystem zu erwarten, aber nur gleichzeitige Kandidaten-Kollisionen sind betrieblich relevant: Jeder Einfügungsversuch wird geprüft und wiederholt. Bei der geplanten Belegung des 11-stelligen Raums sind Wiederholungen praktisch nicht vorhanden.

Eine Alternative wäre die Verschlüsselung oder Anwendung einer schlüsselbasierten Permutation auf eine Sequenznummer. Dies garantiert eindeutige generierte Eingaben, erfordert aber die Verwaltung des Schlüssel-Lebenszyklus und die Zuweisung von Sequenzen. Zufallsgenerierung plus bedingte Einfügung ist einfacher, entfernt die zentrale ID-Zuweisung und ist bei dieser Namensraumgröße ausreichend effizient.

Benutzerdefinierte Aliase teilen sich denselben Primärschlüssel-Namensraum wie generierte Codes. Die Alias-Normalisierung erfolgt vor der Einfügung, und eine global konsistente bedingte Einfügung entscheidet über den Gewinner von gleichzeitigen Anfragen. Reservierte Pfade wie Gesundheit, API, Admin und statisch werden abgelehnt. Wenn Aliase Groß-/Kleinschreibung ignorieren, ist die normalisierte Kleinbuchstabenform der Schlüssel, während die angeforderte Anzeigeform separat gespeichert werden kann.

  1. Datenmodell und Datenbank

Die Felder des autoritativen Link-Datensatzes sind:

code: Primärschlüssel
long_url: Ziel-URL
created_at: Zeitstempel
owner_id: optionale Konto-ID
status: aktiv, deaktiviert oder gelöscht
ttl_or_expiry: optional
version: monoton steigender Wert für Cache-Invalidierung
custom_alias: boolesch

Klickzählungen werden bei jeder Weiterleitung nicht in diesem Datensatz aktualisiert, da dies beliebte Links zu Schreib-Hotspots machen würde.

Der Link-Speicher ist eine verteilte, partitionierte Schlüssel-Wert-Datenbank, die für den Primärschlüsselzugriff optimiert ist, wie z. B. DynamoDB, Bigtable, Cassandra mit sorgfältig verwalteter Konsistenz oder ein äquivalentes intern betriebenes System. Für global eindeutige bedingte Schreibvorgänge muss die ausgewählte Implementierung eine linearisierbare bedingte Erstellung für einen Schlüssel bieten, entweder nativ oder über Shard-weite Konsensführer. Relationale Joins und Bereichsscans sind auf dem Weiterleitungspfad nicht erforderlich.

Der primäre Partitionsschlüssel ist ein Hash des vollständigen Codes. Die Hash-Verteilung verhindert chronologische Hotspots und verteilt sowohl generierte Codes als auch benutzerdefinierte Aliase gleichmäßig. Der logische Schlüsselraum ist in Tausende von virtuellen Shards unterteilt, die neu zugewiesen werden, wenn Knoten hinzugefügt werden. Jeder Shard hat mindestens drei Replikate über Verfügbarkeitszonen hinweg, mit zusätzlichen übergreifenden regionalen Replikaten.

Kapazitätsschätzung

Angenommen, eine durchschnittliche URL von 400 Bytes und etwa 200 Bytes für Schlüssel, Metadaten, Kodierung, Indizes und Overhead der Speicher-Engine. Bei etwa 600 Bytes pro Datensatz benötigen 30 Milliarden Datensätze etwa 18 TB logische Daten. Unter Berücksichtigung längerer URLs, Kompaktierungs-Overhead, Tombstones und operativen Spielraums budgetieren wir 30 TB logische Daten. Drei dauerhafte Replikate erfordern etwa 90 TB, und Backups sowie übergreifende Kopien können die Flottenzuweisung auf etwa 150–250 TB erhöhen. Dies liegt gut im beabsichtigten Bereich von horizontal partitionierten Schlüssel-Wert-Speichern, ist aber für eine einzelne herkömmliche Datenbankinstanz ungeeignet.

Bei 10.000 Weiterleitungen pro Sekunde erzeugt selbst ein vollständiger Cache-Ausfall nur 10.000 zufällige Punktlesevorgänge pro Sekunde. Die Datenbank ist für mindestens 20.000–30.000 Lesevorgänge pro Sekunde pro bedienender Region während eines Failovers und mindestens 1.000 bedingte Erstellungen pro Sekunde ausgelegt. Die Kapazität wird mehr durch die Datensatzgröße, Replikation und Failover-Reserve als durch den normalen Anfrage-Durchsatz bestimmt.

Analysen verwenden separaten Speicher. Ein Stream-Prozessor schreibt pro Code, zeitlich gebündelte Zählungen in einen Analyse-Schlüssel-Wert- oder spaltenorientierten Speicher mit einem Modell wie Code plus Tag oder Stunde als Schlüssel und Zählung als Wert. Eine kompakte Summe kann asynchron aufrechterhalten werden. Die Trennung der Analysen verhindert, dass Zähler für beliebte Links mit Weiterleitungsabfragen konkurrieren.

  1. Caching-Strategie

Jeder Weiterleitungsprozess verfügt über einen begrenzten LRU- oder TinyLFU-In-Memory-Cache für die heißesten Zuordnungen. Ein regionaler Redis- oder Memcached-kompatibler Cluster bildet die zweite Ebene. Zwischengespeicherte Werte umfassen Ziel, Status, Ablaufdatum und Datensatzversion.

Ein repräsentatives Ziel ist eine regionale Cache-Trefferquote von 95–99 Prozent. Zipf-ähnliche URL-Popularität macht dies im Allgemeinen machbar, auch wenn der gesamte Korpus sehr groß ist. Der Cache speichert heiße Objekte, nicht alle 30 Milliarden Links. Zum Beispiel verbrauchen 100 Millionen Einträge zu je etwa 600 Bytes vor Cache-Overhead und vielleicht 100–150 GB in der Praxis, verteilt über einen regionalen Cache-Cluster.

Zuordnungen sind standardmäßig unveränderlich, daher können positive Einträge eine lange TTL haben, z. B. 6–24 Stunden mit Jitter. Wenn Bearbeitung, Deaktivierung oder Löschung unterstützt wird, wird der autoritative Schreibvorgang zuerst committet und dann eine Invalidierung mit dem Code und der neuen Version an alle Regionen gesendet. Kürzere TTLs begrenzen die Zeit für die Auslieferung veralteter Daten, falls eine Invalidierung verloren geht. Sicherheitskritische Deaktivierungsoperationen können auch eine kleine globale Sperrliste in jedem Weiterleitungsprozess platzieren.

Negative Ergebnisse werden etwa 5–30 Sekunden lang zwischengespeichert, um wiederholte Scans abzuwehren. Der Erstellungspfad invalidiert negative Cache-Einträge, nachdem ein Code erfolgreich beansprucht wurde. Die kurze negative TTL begrenzt ein Rennen, bei dem eine andere Region kurzzeitig einen Miss zwischengespeichert hat, bevor die Replikation oder Invalidierung eintraf.

Bei einem Cache-Miss liest der Weiterleitungsdienst die regionale Datenbankreplik und füllt beide Cache-Ebenen. Anforderungskoaleszenz stellt sicher, dass gleichzeitige Misses für einen neu beliebten Code eine Datenbankanfrage statt Tausende auslösen. TTL-Jitter vermeidet synchronisierte Abläufe. Die Datenbank ist so dimensioniert, dass sie die gesamte Last von 10.000 Anfragen pro Sekunde tragen kann, wenn der verteilte Cache ausfällt, wobei eine etwas höhere Latenz akzeptiert wird, während sie funktionsfähig bleibt.

Der Kompromiss von langen Cache-TTLs ist die potenzielle Veralterung nach Bearbeitungen. Unveränderlichkeit, versionierte Invalidierungen und begrenzte TTLs machen diesen Kompromiss explizit. Die Korrektheit der Weiterleitung für neu erstellte Links kann durch synchrone Füllung der erstellenden Region und Weiterleitung einer sofortigen Leseanfrage an diese Region bei Bedarf verbessert werden.

  1. Skalierung und Latenz

Weiterleitungsdienste sind zustandslos und skalieren horizontal basierend auf Anfragen pro Sekunde, CPU und p99-Latenz. Wenn eine Instanz sicher 1.000 Anfragen pro Sekunde verarbeitet, könnte jede Region mindestens 15–20 Instanzen für eine regionale Failover-Last von 10.000 Anfragen pro Sekunde betreiben, zuzüglich Headroom für Bereitstellung und Zonenfehler. Die tatsächliche Dimensionierung wird durch Lasttests ermittelt.

Ein normales Latenzbudget für Cache-Treffer beträgt etwa 2–5 ms für Lastausgleich und Anwendungsarbeit, 1–3 ms für eine In-Prozess-Suche oder 2–8 ms für eine regionale verteilte Cache-Suche und einige Millisekunden für die Erstellung der Antwort. Ein Cache-Miss-Budget weist etwa 10–25 ms für eine lokale replizierte Datenbank-Punktabfrage zu. Diese Budgets lassen Raum, um die p99-Latenz auf der Serverseite unter 50 ms zu halten.

Strikte Hop-zu-Hop-Timeouts verhindern, dass ein beschädigter Cache oder eine beschädigte Replik das gesamte Latenzbudget verbraucht. Der Cache-Zugriff kann auf etwa 8 ms und der Datenbankzugriff auf etwa 25–30 ms begrenzt sein, mit Wiederholungsversuchen nur, wenn noch genügend Budget vorhanden ist. Hedged Reads zu einer zweiten lokalen Replik können für das langsamste Perzentil verwendet werden, sind aber verzögert und ratenbegrenzt, um die normale Last nicht zu verdoppeln.

Schlüssel werden über virtuelle Shards hash-partitioniert. Zufällig generierte Codes gleichen den Datenverkehr natürlich aus, während ein außergewöhnlich heißer einzelner Link durch In-Prozess- und regionale Caches absorbiert wird. Wenn ein heißer Schlüssel die Datenbank erreicht, verhindern Anforderungskoaleszenz und replizierte Lesevorgänge, dass ein Speicher-Knoten zum Engpass wird.

Autoskalierung sorgt für ausreichende Kapazität für den Verlust einer gesamten Verfügbarkeitszone und mindestens eine Region, die Weiterleitungsverkehr von einem ausgefallenen Partner empfängt. Regionen laufen unter etwa 50–60 Prozent der Spitzenkapazität. Der Kompromiss ist höhere Leerlaufkosten im Austausch für das Verfügbarkeitsziel von 99,99 Prozent.

  1. Zuverlässigkeit und Fehlerbehandlung

Verfügbarkeitsziel

Ein monatliches Ziel von 99,99 Prozent erlaubt etwa 4,4 Minuten Nichtverfügbarkeit in einem 30-Tage-Monat. Kein einzelner Cache-Knoten, keine Anwendungsinanz, keine Verfügbarkeitszone oder Region darf für Weiterleitungen erforderlich sein.

Ausfall einer Anwendungsinanz oder -zone

Health Checks entfernen ausgefallene Instanzen und Lastausgleichsmechanismen verteilen Anfragen über mindestens drei Zonen. Dienste verwenden Rolling- oder Canary-Deployments, Connection Draining und automatisiertes Rollback. Die regionale Kapazität übersteht den Verlust einer Zone.

Ausfall eines Cache-Knotens oder -Clusters

Cache-Knoten werden innerhalb einer Region geshardet und repliziert. Wenn ein einzelner Knoten ausfällt, übernimmt seine Replik. Wenn der gesamte Cache nicht verfügbar ist, verwenden Weiterleitungsdienste Circuit Breaker, überspringen Cache-Aufrufe und fragen die Datenbank direkt ab. Datenbankkapazität und Anwendungspool sind explizit für diesen Modus ausgelegt. Admission Control schützt die Datenbank vor unbegrenztem Scanner-Verkehr.

Ausfall eines Datenbank-Knotens

Jeder Shard wird über Zonen hinweg mit Quorum oder Konsens repliziert. Ein ausgefallener Leader wird automatisch ersetzt; Lesevorgänge verwenden eine andere gesunde lokale Replik. Bedingte Erstellungen bleiben während der kurzen Wahl für einen Shard nicht verfügbar, anstatt doppelte Eigentümerschaft zu riskieren. Weiterleitungen können von Replikaten und Caches fortgesetzt werden. Dies bevorzugt die Korrektheit bei der Erstellung, während die Lese-Verfügbarkeit erhalten bleibt.

Ausfall einer Region

Die globale gesundheitsbasierte Weiterleitung entfernt die ausgefallene Region und leitet den Verkehr an die nächstgelegene gesunde Region weiter. Jede bedienende Region verfügt über eine replizierte Kopie der Link-Daten und eine unabhängige Infrastruktur für Weiterleitung, Cache und Ereigniserfassung. Die Cache-Trefferquote ist nach einem Failover zunächst niedriger, daher behalten Standby-Regionen warme Caches für global heiße Links und genügend Datenbank-/Lese-Kapazität für den Kalt-Cache-Anstieg bei.

Bei generierten Codes kann die globale Replikation nach einer konsensgestützten autoritativen Einfügung asynchron erfolgen, wenn die Datenbankarchitektur jeden Schlüssel an einen Home-Shard weiterleitet. Bei benutzerdefinierten Aliassen muss die autoritative bedingte Einfügung global serialisiert bleiben. Wenn ein neu erstellter Link eine überlebende Region vor einem katastrophalen Verlust nicht erreicht hat, kann der Dienst kurzzeitig einen wiederholbaren Fehler anstelle einer falschen Zuordnung zurückgeben. Eine stärkere synchrone Multi-Region-Replikation reduziert dieses Recovery-Point-Fenster, erhöht aber die Erstellungslatenz. Die bevorzugte Konfiguration committet die Link-Erstellung über Replikate in mindestens zwei Regionen, da Schreibvorgänge relativ geringvolumig sind.

Backups und Korruption

Die Datenbank verwendet Prüfsummen, Point-in-Time-Wiederherstellung, unveränderliche Snapshots und regelmäßig getestete Wiederherstellungsverfahren. Löschungen verwenden Tombstones und eine Aufbewahrungsfrist anstelle einer sofortigen physischen Entfernung. Backups schützen vor logischer Korruption, sind aber kein Teil des normalen Weiterleitungs-Failovers.

Verhalten bei Überlastung

Ratenbegrenzungen gelten nach Quelle, Konto und verdächtigen Code-Scanning-Mustern. Erstellungs- und Analyse-Traffic haben eine niedrigere Priorität als Weiterleitungen. Load Shedding lehnt missbräuchliche oder übermäßige Erstellungsanfragen ab, bevor die Weiterleitungs-Kapazität beeinträchtigt wird. Circuit Breaker, begrenzte Warteschlangen und Timeouts verhindern kaskadierende Fehler.

  1. Klick-Analysen

Nach Auswahl des Weiterleitungsziels erstellt der Dienst ein kompaktes Ereignis mit einer Ereignis-ID, einem Code, einem Zeitstempel, einer Region und optional groben Verweis- oder User-Agent-Feldern. Er platziert das Ereignis in einen begrenzten lokalen asynchronen Puffer und gibt die Weiterleitung zurück, ohne auf die Bestätigung der Analysen zu warten.

Ein regionaler Collector bündelt Ereignisse in einen dauerhaften replizierten Stream wie Kafka, Pulsar oder Kinesis. Stream-Prozessoren aggregieren Ereignisse nach Code und Zeit-Bucket und schreiben dann gebündelte Inkremente in den Analyse-Speicher. Regelmäßige Kompaktierung erzeugt Gesamt-Klickzahlen. Dashboards und APIs lesen den Analyse-Speicher, niemals die autoritative Weiterleitungs-Tabelle.

Ereignis-IDs ermöglichen die nachgelagerte Deduplizierung, wenn Collector erneut versuchen. Die Partitionierung des Streams direkt nach Code würde einen viralen Link auf eine Partition konzentrieren, daher kann der Ingestionsschlüssel Code plus ein zufälliges Stripe sein. Prozessoren aggregieren zuerst gestreifte Zähler und verschmelzen sie dann. Dies ermöglicht die horizontale Skalierung von Hot-Link-Analysen.

Ein rein asynchroner In-Memory-Puffer kann Ereignisse verlieren, wenn ein Weiterleitungsprozess abstürzt. Wenn eine stärkere Dauerhaftigkeit erforderlich ist, kann jeder Host oder Sidecar Batches in ein lokales Write-Ahead-Log anhängen, bevor er sie weiterleitet, aber Weiterleitungsantworten sollten immer noch nicht auf den zentralen Stream warten. Der akzeptierte Kompromiss für grundlegende Analysen ist die endgültige Konsistenz und eine kleine, gemessene Unterzählung während schwerer Ausfälle, im Austausch für die Beibehaltung der Weiterleitungs-Latenz und -Verfügbarkeit.

Ergebnis

Der normale Weiterleitungspfad ist eine lokale Cache-Suche, gefolgt, nur bei Misses, von einer lokalen partitionierten Schlüssel-Wert-Suche. Zufällige 11-stellige Codes verhindern sequentielle Offenlegung und machen erfolgreiches Raten im großen Stil unpraktisch. Bedingte Einfügungen sorgen für Eindeutigkeit, Hash-Partitionierung unterstützt den 30-Milliarden-Datensatz-Korpus, aktiv-aktive regionale Bedienung eliminiert regionale Single Points of Failure und asynchrone gestreifte Analysen halten Zähler-Schreibvorgänge vollständig vom Latenz-kritischen Pfad fern.

Ergebnis

#1 | Sieger

Siegstimmen

3 / 3

Durchschnittsscore

90
Bewertungsmodelle Anthropic Claude Fable 5

Gesamtpunktzahl

86

Gesamtkommentar

Antwort A ist ein außergewöhnlich gründliches und technisch fundiertes Design-Dokument. Sie knüpft jede Hauptentscheidung an die angegebenen Einschränkungen: Sie leitet die Schreibrate sowohl aus dem Verhältnis 100:1 als auch aus der Angabe 30B/5 Jahre ab und gleicht die Diskrepanz aus, berechnet explizit, dass ein 7-stelliger Speicherplatz bei 0,85% Belegung (ungefähr 1 Treffer pro 117 Vermutungen) aufzählbar wäre und geht daher zu 11-stelligen Zufallscodes über, liefert eine begründbare Speicherplatzschätzung pro Datensatz und auf Flottenebene (ca. 18 TB logisch, 90 TB repliziert, 150-250 TB mit Backups), gibt ein konkretes Latenzbudget für p99, aufgeteilt in Allokationen pro Hop mit Timeouts und abgesicherten Lesevorgängen, und übersetzt 99,99% in 4,4 Minuten/Monat mit geschichteter Fehlerbehandlung für Instanzen, Caches, Datenspeicher-Shards und ganze Regionen. Kompromisse werden durchweg ehrlich benannt (längere Codes vs. Aufzählbarkeit, schreibende Latenz über Regionen hinweg vs. globale Einzigartigkeit, Leerlaufkapazität vs. Spielraum für Failover, Analyse-Untererfassung vs. Weiterleitungslatenz). Schwächen sind geringfügig: Die Antwort ist lang und dicht, einige Zahlen zur Dimensionierung werden behauptet statt abgeleitet, und eine Zusammenfassung im Diagrammformat würde die Scanbarkeit verbessern. Insgesamt übertrifft sie die Benchmark-Erwartungen in fast jeder Hinsicht.

Bewertungsdetails anzeigen

Architekturqualität

Gewichtung 30%
87

Kohärente Active-Active-Multi-Region-Architektur mit klar getrennten Erstellungs-/Weiterleitungspfaden, bedingten Einfügungen zur Einzigartigkeit, zweistufigem Caching mit Anforderungsbündelung und einer korrekten quantifizierten Ablehnung von 7-stelligen Codes (0,85% Belegung macht Massenratenraten möglich), was zu 11-stelligen CSPRNG-Codes führt. Jede Komponentenentscheidung ist an eine Einschränkung gebunden. Geringfügige Abzüge für Dichte und einige behauptete statt abgeleitete Dimensionierungszahlen.

Vollständigkeit

Gewichtung 20%
90

Alle sieben nummerierten Anforderungen werden mit konkreten Details behandelt: Annahmen werden vorab dargelegt, Schreibraten-Abgleich, vollständige Code-Generierungsanalyse mit Alias-Kollisionsrichtlinie, Speicherberechnung für 30 Milliarden Datensätze, explizites Cache-Miss- und Invalidierungsverhalten, Latenzbudget pro Hop für p99 unter 50 ms, Fehlerbehandlung auf jeder Ebene, die auf das Budget von 4,4 Minuten/Monat abgebildet wird, und gestreifte asynchrone Analysen mit Durabilitäts-Kompromissen.

Trade-off-Analyse

Gewichtung 20%
85

Kompromisse werden durchweg benannt und quantifiziert: 4 zusätzliche Zeichen vs. Aufzählbarkeit mit tatsächlicher Wahrscheinlichkeitsmathematik, Latenz bei der Konsensschreibung über Regionen hinweg vs. globale Einzigartigkeit, lange TTLs vs. Veralterung, die durch versionierte Invalidierungen begrenzt ist, Leerlaufkapazität unter 50-60% Auslastung vs. Verfügbarkeit und akzeptierte Analyse-Untererfassung vs. Weiterleitungslatenz. Alternativen (Schlüsselpermutation von Sequenzen) werden mit Gründen erwogen und abgelehnt.

Skalierbarkeit und Zuverlässigkeit

Gewichtung 20%
85

Konkrete Skalierungsgeschichte: Hash-partitionierte virtuelle Shards, Instanzdimensionierung mit Failover-Spielraum, Datenspeicher, der so bereitgestellt ist, dass er die vollen 10K RPS bei einem vollständigen Cache-Ausfall absorbieren kann, abgesicherte Lesevorgänge und Timeouts pro Hop, Übersetzung von 99,99% in 4,4 Minuten/Monat und geschichtete Fehlerbehandlung, die Instanz-, Zonen-, Cache-, Shard-Leader-Wahl und vollständigen Regionsverlust mit Warm-Standby-Caches abdeckt. RPO-Kompromiss für die regionsübergreifende Replikation wird explizit diskutiert.

Klarheit

Gewichtung 10%
80

Gut organisiert mit nummerierten Abschnitten, die der Aufforderung entsprechen, expliziten Annahmen und einer abschließenden Zusammenfassung. Der Text ist dicht und lang, und einige Abschnitte packen viele Zahlen in Absätze, wo Tabellen oder Aufzählungszeichen helfen würden, aber der Argumentationsfluss ist immer nachvollziehbar.

Bewertungsmodelle OpenAI GPT-5.5

Gesamtpunktzahl

92

Gesamtkommentar

Antwort A ist ein sehr starkes, konkretes Systemdesign. Es verknüpft die Architektur explizit mit den 10.000 RPS, dem Lese-/Schreibverhältnis von 100:1, p99 unter 50 ms, dem 30 Milliarden Links umfassenden Korpus, dem Verfügbarkeitsziel von 99,99 % und der Anforderung der Nicht-Erratbarkeit. Es bietet kohärente Lese- und Schreibflüsse, eine starke Kurzcode-Strategie, plausible Speichergrößen, detailliertes Caching-Verhalten, Partitionierung, Multi-Region-Zuverlässigkeit und asynchrone Analysen. Seine Hauptschwäche ist, dass es etwas aufwendig ist, aber die Details sind größtenteils relevant und gut begründet.

Bewertungsdetails anzeigen

Architekturqualität

Gewichtung 30%
92

Antwort A liefert eine kohärente End-to-End-Architektur mit separaten Erstellungs- und Umleitungspfaden, lokalem und verteiltem Caching, autoritativem Schlüssel-Wert-Speicher, Event-Streaming, aktiven/aktiven Regionen und klaren normalen und Fehleranforderungsflüssen. Die Designentscheidungen passen zur Workload und den Latenzbeschränkungen.

Vollständigkeit

Gewichtung 20%
95

Antwort A behandelt jeden erforderlichen Abschnitt im Detail: Schreib-/Leseflüsse, Einzigartigkeit, Kollisionen benutzerdefinierter Aliase, Datenspeicher- und Kapazitätsschätzung, Cache-Miss- und Invalidierungsverhalten, Skalierung und Sharding, Ausfälle von Knoten/Caches/Regionen und asynchrone Analysen. Sie gibt auch Annahmen klar an.

Trade-off-Analyse

Gewichtung 20%
91

Antwort A nennt durchweg Kompromisse, wie z. B. längere Codes gegenüber der Widerstandsfähigkeit gegen Enumeration, Latenz bei Schreibvorgängen im Quorum oder in mehreren Regionen gegenüber der Einzigartigkeit, Veralterung des Cache-TTL gegenüber der Geschwindigkeit, Kosten für zusätzliche Kapazität gegenüber der Verfügbarkeit und Risiko von Analyse-Verlusten gegenüber der Umleitungslatenz.

Skalierbarkeit und Zuverlässigkeit

Gewichtung 20%
92

Antwort A liefert glaubwürdige Skalierungs- und Zuverlässigkeitsdetails: zustandslose horizontale Skalierung, Hash-Partitionierung mit virtuellen Shards, Cache-Größenbestimmung und Fallback, Bereitstellung von Datenspeichern für Cache-Ausfälle, aktive/aktive Multi-Region-Bereitstellung, regionales Failover, Quorum-/Konsensverhalten und asynchrone Analysen, die Hot-Path-Schreibvorgänge vermeiden.

Klarheit

Gewichtung 10%
90

Antwort A ist gut organisiert, strukturiert nach den erforderlichen Abschnitten und verwendet konkrete Zahlen und Mechanismen. Sie ist lang, aber die Struktur macht das Design leicht verständlich.

Bewertungsmodelle Google Gemini 2.5 Pro

Gesamtpunktzahl

92

Gesamtkommentar

Antwort A bietet ein herausragendes und umfassendes Systemdesign. Sie zeichnet sich dadurch aus, dass sie jede Einschränkung direkt mit spezifischen, gut begründeten technischen Entscheidungen anspricht. Ihre Analyse der Erratbarkeit kurzer Codes und der Vorschlag eines 11-stelligen Zufallscodes ist eine Kernstärke. Die Kapazitätsplanung ist detailliert und realistisch, und die Multi-Region-Active-Active-Architektur bietet einen glaubwürdigen Weg zur Erreichung des Verfügbarkeitsziels von 99,99 %. Die Diskussion von Fehlermodi auf jeder Ebene (Knoten, Cache, Region) ist gründlich und zeigt ein tiefes Verständnis für den Aufbau robuster Systeme.

Bewertungsdetails anzeigen

Architekturqualität

Gewichtung 30%
90

Die Architektur ist ausgezeichnet. Sie schlägt von Anfang an korrekt ein Multi-Region-Active-Active-Setup vor, was für die globale Natur und die hohen Verfügbarkeitsanforderungen angemessen ist. Die Komponenten sind gut definiert, und die Anfrageflüsse für Lese- und Schreibpfade sind detailliert und logisch.

Vollständigkeit

Gewichtung 20%
95

Die Antwort ist außergewöhnlich vollständig und behandelt alle sieben erforderlichen Abschnitte mit erheblicher Detailtiefe. Jede funktionale und nicht-funktionale Anforderung wird mit einer spezifischen Designentscheidung abgedeckt.

Trade-off-Analyse

Gewichtung 20%
90

Die Abwägung von Kompromissen ist eine Hauptstärke dieser Antwort. Für fast jede signifikante Entscheidung (z. B. Code-Länge, Wahl des Datenspeichers, Cache-TTL, Replikationsstrategie) wird der spezifische Kompromiss explizit angegeben und im Kontext der Anforderungen begründet.

Skalierbarkeit und Zuverlässigkeit

Gewichtung 20%
95

Dies ist der stärkste Teil der Antwort. Sie identifiziert korrekt, dass 7-stellige Codes bei einer Skala von 30 Milliarden erratbar werden, und schlägt eine robuste Lösung vor. Die Kapazitätsschätzung ist gründlich und realistisch. Der Zuverlässigkeitsplan ist ausgezeichnet und deckt Ausfälle auf Instanz-, Zonen-, Cache-, Datenspeicher- und regionaler Ebene ab, was einen glaubwürdigen Weg zur Erreichung einer Verfügbarkeit von 99,99 % bietet.

Klarheit

Gewichtung 10%
85

Das Dokument ist sehr gut strukturiert, klar und technisch dicht. Es folgt präzise dem geforderten Format, was die Bewertung des Designs anhand der Anforderungen erleichtert.

Systemdesign: URL-Kürzer (10.000 Anfragen pro Sekunde)

Annahmen:

  • Wir entwickeln zunächst für eine einzelne Region, wobei Multi-Region eine zukünftige Verbesserung darstellt.
  • Der Schwerpunkt liegt aufgrund des Lese-Schreib-Verhältnisses von 100:1 auf dem Weiterleitungspfad.
  • Benutzerdefinierte Aliase sind eine sekundäre Funktion und können im Vergleich zu Standardweiterleitungen etwas höhere Latenzzeiten oder gelegentliche Nichtverfügbarkeit tolerieren.
  • Klickanalysen sind nicht streng in Echtzeit und können eine leichte Verzögerung aufweisen.

1. High-Level-Architektur und Anfragefluss...

Vollständige Antwort anzeigen

Systemdesign: URL-Kürzer (10.000 Anfragen pro Sekunde)

Annahmen:

  • Wir entwickeln zunächst für eine einzelne Region, wobei Multi-Region eine zukünftige Verbesserung darstellt.
  • Der Schwerpunkt liegt aufgrund des Lese-Schreib-Verhältnisses von 100:1 auf dem Weiterleitungspfad.
  • Benutzerdefinierte Aliase sind eine sekundäre Funktion und können im Vergleich zu Standardweiterleitungen etwas höhere Latenzzeiten oder gelegentliche Nichtverfügbarkeit tolerieren.
  • Klickanalysen sind nicht streng in Echtzeit und können eine leichte Verzögerung aufweisen.

1. High-Level-Architektur und Anfragefluss

Schreibpfad (Kurzlink erstellen):

  1. API-Gateway: Empfängt die POST-Anfrage mit der langen URL und dem optionalen benutzerdefinierten Alias.
  2. Lastverteiler: Verteilt Schreibanfragen auf die Instanzen der URL-Shortening-Service (US) API.
  3. US API (Schreibdienst):
    • Validiert die Eingabe-URL.
    • Generiert einen Kurzcode (siehe Abschnitt 2).
    • Wenn ein benutzerdefinierter Alias angegeben ist, versucht er zuerst, diesen zu reservieren (siehe Abschnitt 2).
    • Speichert die Zuordnung (Kurzcode -> ursprüngliche URL, benutzerdefinierter Alias -> Kurzcode) im Datenspeicher.
    • Gibt die generierte Kurz-URL an den Client zurück.

Lesepfad (Weiterleitung):

  1. API-Gateway: Empfängt die GET-Anfrage für eine Kurz-URL.
  2. Lastverteiler: Verteilt Leseanfragen auf die US-API-Instanzen.
  3. US API (Lesedienst):
    • Extrahiert den Kurzcode aus dem URL-Pfad.
    • Cache-Abfrage: Überprüft einen verteilten Cache (z. B. Redis Cluster) auf den Kurzcode.
      • Cache-Treffer: Wenn gefunden, wird die ursprüngliche URL abgerufen und eine HTTP-301/302-Weiterleitungsantwort zurückgegeben.
      • Cache-Fehlgriff: Wenn nicht gefunden, wird der primäre Datenspeicher abgefragt.
    • Datenspeicher-Abfrage: Fragt den primären Datenspeicher nach der ursprünglichen URL ab, die dem Kurzcode zugeordnet ist.
    • Cache-Aktualisierung: Wenn im Datenspeicher gefunden, wird die ursprüngliche URL für zukünftige Anfragen in den Cache geschrieben.
    • Weiterleitung: Gibt eine HTTP-301/302-Weiterleitungsantwort mit der ursprünglichen URL zurück.
    • Fehlerbehandlung: Wenn nicht gefunden, wird ein 404 Not Found zurückgegeben.
  4. Klickanalysen (Asynchron): Ein separater Dienst oder Mechanismus (siehe Abschnitt 7) zeichnet Klickereignisse asynchron auf.

Kompromisse:

  • Trennung von Belangen: Die Trennung von Lese- und Schreibdiensten ermöglicht unabhängige Skalierung und Optimierung. Der Lesepfad ist für geringe Latenz und hohen Durchsatz optimiert.
  • API-Gateway/Lastverteiler: Führt einen einzigen Fehlerpunkt ein, wenn er nicht für hohe Verfügbarkeit konfiguriert ist, ist aber für Skalierung und Verkehrsmanagement unerlässlich.
  • Cache-Fehlgriff-Strafe: Ein Cache-Fehlgriff verursacht aufgrund der Datenspeicherabfrage höhere Latenzzeiten, dies wird jedoch durch einen großen Cache und eine hohe Trefferquote gemildert.

2. Strategie zur Generierung von Kurzcodes

Strategie: Base62-Kodierung mit einem Zähler/ID-Generator.

  1. ID-Generierung: Wir verwenden einen verteilten ID-Generierungsdienst (z. B. Snowflake-ähnlich oder einen dedizierten Dienst mit ZooKeeper/etcd), um eindeutige, monoton steigende 64-Bit-Integer zu generieren. Dies gewährleistet Eindeutigkeit und vermeidet Kollisionen an der Quelle.
    • Kompromiss: Erfordert einen hochverfügbaren und performanten ID-Generierungsdienst. Wenn er ausfällt, können keine neuen Kurzlinks erstellt werden.
  2. Base62-Kodierung: Jeder generierte 64-Bit-Integer-ID wird in eine Base62-Zeichenkette (0-9, a-z, A-Z) umgewandelt. Eine 64-Bit-ID kann bis zu 2^64 eindeutige Werte darstellen. Die ersten 6 Zeichen können ungefähr 68 Milliarden eindeutige Werte darstellen (62^6), und 7 Zeichen können ungefähr 4,1 Billionen (62^7) darstellen. Für 30 Milliarden Links über 5 Jahre sind 7 Zeichen ausreichend und bieten viel Spielraum für Wachstum.
    • Kompromiss: Die Base62-Kodierung ist etwas komplexer als einfaches Hashing, liefert aber kürzere URLs und vermeidet im Vergleich zu sequenziellen IDs eine Erratbarkeit.
  3. Benutzerdefinierte Aliase:
    • Wenn ein Benutzer einen benutzerdefinierten Alias anfordert (z. B. /mein-link), prüft der Schreibdienst zuerst, ob der Alias in einer dedizierten Tabelle/einem Index im Datenspeicher (z. B. Tabelle custom_aliases, die alias -> short_code abbildet) bereits vergeben ist.
    • Wenn der Alias verfügbar ist, wird er reserviert und dem neu generierten Kurzcode zugeordnet.
    • Wenn der Alias vergeben ist, gibt die API eine Fehlermeldung an den Benutzer zurück.
    • Kollisionsbehandlung: Die ID-Generierung und Base62-Kodierung gewährleisten die Eindeutigkeit für generierte Kurzcodes. Benutzerdefinierte Aliase werden über eine separate, atomare Prüf-und-Setz-Operation im Datenspeicher behandelt, um Kollisionen zu vermeiden.
    • Kompromiss: Abfragen benutzerdefinierter Aliase verursachen einen geringen Mehraufwand für den Schreibpfad. Die Verfügbarkeit benutzerdefinierter Aliase ist nicht garantiert.

Eindeutigkeitsgarantie: Erreicht durch den verteilten ID-Generator. Jede ID ist eindeutig, und ihre Base62-Darstellung wird ebenfalls eindeutig sein.

Nicht erratbar: Base62-kodierte IDs sind nicht sequenziell und verraten nicht die Reihenfolge der Erstellung oder die Gesamtzahl der Links. Sie sind effektiv zufällig aussehende Zeichenketten.

3. Datenmodell und Datenspeicher

Wahl des Datenspeichers: Ein verteilter NoSQL-Schlüssel-Wert-Speicher (z. B. Cassandra, DynamoDB oder eine geshardete relationale Datenbank wie Vitess) für die primäre Link-Zuordnung und ein separates System für Analysen.

Primärer Datenspeicher (Link-Zuordnung):

  • Schema:

    • links-Tabelle/Sammlung:
      • short_code (Primärschlüssel, String, z. B. "aBcDeFg")
      • original_url (String)
      • created_at (Zeitstempel)
      • user_id (Optional, für Eigentümerschaft/Verwaltung)
    • custom_aliases-Tabelle/Sammlung:
      • alias (Primärschlüssel, String, z. B. "mein-link")
      • short_code (String, Fremdschlüssel zu links.short_code)
  • Begründung des Datenspeichertyps: Ein verteilter NoSQL-Schlüssel-Wert-Speicher wird wegen seiner hohen Verfügbarkeit, horizontalen Skalierbarkeit und hervorragenden Leseleistung für Schlüsselabfragen bevorzugt, was für den Weiterleitungspfad entscheidend ist. Er kann die massive Skalierung von 30 Milliarden Einträgen bewältigen.

  • Kapazitäts-/Speicherschätzung:

    • Links-Tabelle: 30 Milliarden Einträge.
      • short_code: ca. 7 Bytes (Base62, 7 Zeichen)
      • original_url: Durchschnittlich 100 Bytes (kann stark variieren, Durchschnitt annehmen)
      • created_at, user_id: ca. 10 Bytes
      • Gesamt pro Eintrag: ca. 117 Bytes. Aufrunden auf 150 Bytes für Overhead und Replikation.
      • Gesamtspeicher: 30 Milliarden * 150 Bytes = 4,5 * 10^12 Bytes = 4,5 TB.
    • Tabelle für benutzerdefinierte Aliase: Angenommen, 10 % der Links haben benutzerdefinierte Aliase (3 Milliarden).
      • alias: Durchschnittlich 15 Bytes (kürzer als lange URLs).
      • short_code: ca. 7 Bytes.
      • Gesamt pro Eintrag: ca. 22 Bytes. Aufrunden auf 50 Bytes für Overhead.
      • Gesamtspeicher: 3 Milliarden * 50 Bytes = 150 * 10^9 Bytes = 0,15 TB.
    • Gesamtspeicher primär: ca. 4,65 TB. Dies ist für verteilte NoSQL-Systeme überschaubar.
  • Partitionierung/Sharding: Der Datenspeicher wird nach short_code (für die links-Tabelle) und alias (für die custom_aliases-Tabelle) geshardet. Dies ermöglicht eine gleichmäßige Verteilung von Daten und Last über die Knoten.

Kompromisse:

  • NoSQL vs. SQL: Ein NoSQL-Speicher wird wegen seiner Schemaflexibilität und horizontalen Skalierbarkeit bevorzugt. Eine relationale Datenbank könnte funktionieren, würde aber eine komplexere Sharding-Verwaltung erfordern (z. B. Vitess).
  • Datenredundanz: NoSQL-Speicher replizieren Daten typischerweise zur Verfügbarkeit, was den Speicherbedarf erhöht, aber die Fehlertoleranz verbessert.
  • Tabelle für benutzerdefinierte Aliase: Eine separate Tabelle wird verwendet, um die Verfügbarkeit von Aliasen effizient zu prüfen, ohne die Haupttabelle links durchsuchen zu müssen, was ineffizient wäre.

4. Caching-Strategie

Strategie: Verteilter In-Memory-Cache (z. B. Redis Cluster, Memcached).

  • Was wird gecacht: Häufig abgerufene Zuordnungen von short_code zu original_url.
  • Cache-Schlüssel: short_code (z. B. "aBcDeFg")
  • Cache-Wert: original_url (z. B. "https://www.sehrlangeurl.com/...")
  • Cache-Größe: Ausgelegt, um einen erheblichen Teil der Hot-Links zu speichern. Angesichts von 10.000 Anfragen pro Sekunde und einem Verhältnis von 100:1 erwarten wir Millionen von aktiven Links pro Sekunde. Ein Cache mit 1-5 Millionen Einträgen sollte für Hot-Links eine hohe Trefferquote bieten.
  • Cache-Invalidierung:
    • Keine explizite Invalidierung für Standardlinks erforderlich: Sobald Links erstellt sind, sind sie unveränderlich. Die Zuordnung ändert sich nicht.
    • Für benutzerdefinierte Aliase: Wenn ein benutzerdefinierter Alias geändert wird (normalerweise nicht erlaubt, aber wenn es so wäre), würde die alte Zuordnung short_code -> original_url im Cache verbleiben. Die Standardpraxis ist jedoch, dass benutzerdefinierte Aliase eindeutig und nach der Festlegung dauerhaft sind. Wenn ein Link gelöscht wird (keine übliche Funktion für URL-Kürzer), würde der Eintrag aus dem Cache entfernt.
  • Behandlung von Cache-Fehlgriffen:
    1. Bei einem Cache-Fehlgriff fragt die US-API (Lesedienst) den primären Datenspeicher nach der original_url unter Verwendung des short_code ab.
    2. Wenn im Datenspeicher gefunden, wird die original_url mit einer Time-To-Live (TTL) (z. B. 24-48 Stunden) zurück in den Cache geschrieben, bevor sie an den Client zurückgegeben wird.
    3. Wenn im Datenspeicher nicht gefunden, wird ein 404 zurückgegeben und kein Eintrag in den Cache aufgenommen.

Kompromisse:

  • Cache-Veralterung: TTL-basiertes Caching bedeutet, dass es ein kleines Zeitfenster gibt, in dem ein Link aktualisiert werden könnte (wenn Updates erlaubt wären) und der Cache veraltet wäre. Bei unveränderlichen Links ist dies jedoch kein Problem.
  • Cache-Verfügbarkeit: Der Cache ist eine kritische Komponente. Wenn er ausfällt, erhöht sich die Latenz aufgrund von Datenspeicherabfragen erheblich, aber der Dienst bleibt verfügbar (wenn auch langsamer).
  • Kosten: Große In-Memory-Caches können teuer sein.

5. Skalierungsstrategie

Skalierung des Lesepfads (Weiterleitungen):

  • Zustandslose API-Server: Die US-API-Instanzen, die Weiterleitungen verarbeiten, sind zustandslos. Dies ermöglicht es uns, sie hinter einem Lastverteiler unbegrenzt horizontal zu skalieren.
  • Verteilter Cache: Ein geshardeter und replizierter verteilter Cache (wie Redis Cluster) kann Millionen von Anfragen pro Sekunde verarbeiten und bietet geringe Latenz. Er ist für die horizontale Skalierung ausgelegt.
  • Datenspeicher-Skalierung: Der gewählte verteilte NoSQL-Datenspeicher (Cassandra, DynamoDB) ist für die horizontale Skalierung ausgelegt. Wir können weitere Knoten hinzufügen, um den Durchsatz und die Kapazität zu erhöhen.
  • Lastverteiler: Lastverteiler auf mehreren Ebenen (API-Gateway, Service-zu-Service-intern) verteilen den Verkehr gleichmäßig.

Datenpartitionierung/Sharding:

  • Datenspeicher-Sharding: Wie in Abschnitt 3 erwähnt, wird der primäre Datenspeicher nach short_code (oder einem Hash davon) für die links-Tabelle und alias für die custom_aliases-Tabelle geshardet. Dies verteilt Daten und Lese-/Schreiblast über mehrere Knoten.
  • Cache-Sharding: Der verteilte Cache ist von Natur aus geshardet und verteilt Schlüssel über seine Knoten.
  • ID-Generierungsdienst: Dieser Dienst muss ebenfalls skalierbar sein, möglicherweise unter Verwendung mehrerer Instanzen, die von ZooKeeper/etcd oder einem verteilten Konsensprotokoll koordiniert werden.

Kompromisse:

  • Komplexität: Sharding und verteilte Systeme erhöhen die betriebliche Komplexität erheblich.
  • Hotspots: Obwohl Sharding hilft, könnten extrem beliebte Links immer noch Hotspots auf bestimmten Cache-Shards oder Datenspeicherpartitionen erzeugen. Strategien wie konsistentes Hashing oder fortschrittlichere Lastverteilung können dies mildern.

6. Zuverlässigkeit und Fehlerbehandlung

Verfügbarkeitsziel (99,99 %): Erfordert Redundanz auf jeder Ebene.

  • Ausfall eines Datenspeicherknotens:
    • Strategie: Daten werden über mehrere Knoten (z. B. 3-5 Replikate) und möglicherweise über Verfügbarkeitszonen innerhalb einer Region repliziert.
    • Behandlung: Der Datenspeicher-Cluster behandelt Knotenausfälle automatisch, indem er ein Replikat befördert und weiterhin Anfragen bedient. Lese- und Schreibvorgänge können während eines Failovers eine kurze Latenzspitze erfahren, aber der Dienst bleibt verfügbar.
    • Kompromiss: Erhöhte Speicherkosten aufgrund der Replikation.
  • Ausfall eines Cache-Knotens:
    • Strategie: Verteilte Caches wie Redis Cluster sind mit Replikation und Sharding konzipiert. Wenn ein Knoten ausfällt, können seine Replikate übernehmen oder die Daten neu verteilt werden.
    • Behandlung: Cache-Fehlgriffe nehmen vorübergehend zu, während der Cache neu aufgebaut wird oder ein Failover stattfindet. Das System greift auf den Datenspeicher zurück, was zu höheren Latenzen, aber fortgesetzter Verfügbarkeit führt.
    • Kompromiss: Vorübergehende Leistungsverschlechterung bei Cache-Ausfall.
  • Ausfall eines API-Servers:
    • Strategie: Mehrere Instanzen der zustandslosen US-API-Server hinter Lastverteilern ausführen.
    • Behandlung: Lastverteiler erkennen fehlerhafte Instanzen und hören auf, ihnen Verkehr zuzusenden. Der Verkehr wird automatisch an fehlerfreie Instanzen weitergeleitet.
    • Kompromiss: Erfordert robuste Lastverteilung und Zustandsprüfung.
  • Ausfall einer Region:
    • Strategie: Den Dienst über mehrere Verfügbarkeitszonen (AZs) innerhalb einer Region bereitstellen. Für höhere Verfügbarkeit kann ein Multi-Region-Aktiv-Aktiv- oder Aktiv-Passiv-Setup implementiert werden.
    • Behandlung: Wenn eine AZ ausfällt, wird der Verkehr an fehlerfreie AZs weitergeleitet. Wenn eine gesamte Region ausfällt, wird der Verkehr an eine sekundäre Region weitergeleitet (erfordert globale Lastverteilung und Datenreplikation).
    • Kompromiss: Erhebliche Erhöhung der Komplexität und Kosten für Multi-Region-Bereitstellungen.

Erreichen des Verfügbarkeitsziels: Redundanz, automatische Failover und schrittweise Verschlechterung (Rückgriff auf den Datenspeicher bei Cache-Fehlgriff) sind entscheidend. Überwachung und Alarmierung sind unerlässlich, um Fehler schnell zu erkennen und darauf zu reagieren.

7. Erfassung von Klickanalysen

Strategie: Asynchrone Verarbeitung, um den kritischen Weiterleitungspfad nicht zu beeinträchtigen.

  1. Ereigniserzeugung: Wenn eine Weiterleitung stattfindet (nachdem die ursprüngliche URL abgerufen wurde und bevor die Weiterleitungsantwort gesendet wird), veröffentlicht die US-API (Lesedienst) ein leichtgewichtiges

Ergebnis

#2

Siegstimmen

0 / 3

Durchschnittsscore

53
Bewertungsmodelle Anthropic Claude Fable 5

Gesamtpunktzahl

55

Gesamtkommentar

Antwort B ist ein kompetent strukturiertes Dokument mit klaren Überschriften und expliziten Trade-off-Aufzählungen, weist jedoch erhebliche inhaltliche Mängel auf. Am schwerwiegendsten ist, dass sein Kurzcode-Schema intern inkonsistent ist: Es verwendet einen monoton steigenden Zähler im Snowflake-Stil und behauptet dann, die Base62-Kodierung mache Codes nicht-sequenziell und nicht erratbar, was falsch ist – Base62 von sequenziellen IDs bleibt vollständig aufzählbar und verstößt direkt gegen die angegebene Einschränkung der Nicht-Erratbarkeit. Die Antwort ist außerdem mitten im Satz in Abschnitt 7 abgeschnitten, wodurch die Analyse-Pipeline (eine nummerierte Anforderung) unvollständig bleibt. Weitere Schwächen: Die Speicherschätzung geht von nur 100 Byte durchschnittlichen URLs aus (wahrscheinlich zu niedrig) und multipliziert die Replikation nicht konkret aus; das p99 unter 50 ms Ziel wird nie mit einem Latenzbudget angesprochen; die Begründung für die Cache-Größe (1-5 Millionen Einträge) wird ohne Herleitung behauptet; und die Behandlung von Regionsausfällen wird allgemein als mögliche zukünftige Verbesserung beschrieben, anstatt für das 99,99 %-Ziel ausgelegt zu sein. Stärken sind die lesbare Organisation, die korrekte asynchrone Absicht für die Analyse und vernünftige Datenbankspeicher-/Sharding-Auswahl.

Bewertungsdetails anzeigen

Architekturqualität

Gewichtung 30%
50

Die Gesamtstruktur (Gateway, zustandslose Dienste, Redis-Cache, geshardete NoSQL-Datenbank) ist sinnvoll, aber das Kurzcode-Design ist intern inkonsistent: monoton steigende Snowflake-IDs, die in Base62 kodiert sind, sind immer noch sequenziell und massenhaft aufzählbar, obwohl die Antwort behauptet, sie seien nicht erratbar. Dies verstößt direkt gegen eine angegebene harte Einschränkung und ist ein Korrektheitsfehler im Kern des Designs. Der Rest der Architektur ist kompetent, aber generisch und standardmäßig auf eine Region beschränkt.

Vollständigkeit

Gewichtung 20%
50

Die Abschnitte 1-6 sind auf einem angemessenen Niveau abgedeckt, aber Abschnitt 7 (Klickanalysen) ist mitten im Satz abgebrochen, wodurch eine nummerierte Anforderung unvollständig bleibt. Das p99 unter 50 ms Ziel wird nie mit einem Latenzbudget oder Zahlen angesprochen, und die Multi-Region-Zuverlässigkeit wird als zukünftige Verbesserung aufgeschoben, anstatt ausgelegt zu werden. Die Speicherschätzung ist vorhanden, unterschätzt aber möglicherweise die URL-Größe.

Trade-off-Analyse

Gewichtung 20%
60

Jeder Abschnitt enthält eine explizite Trade-off-Aufzählung, was eine echte Stärke ist, aber mehrere sind oberflächlich oder generisch (z. B. 'Komplexität steigt', 'Replikation erhöht Kosten'). Der wichtigste Trade-off – sequentielle IDs vs. Erratbarkeit – wird falsch gehandhabt: Der Nachteil wird geleugnet, anstatt anerkannt zu werden. Cache- und Skalierungs-Trade-offs werden angegeben, aber nicht anhand der gegebenen Einschränkungen quantifiziert.

Skalierbarkeit und Zuverlässigkeit

Gewichtung 20%
55

Standardmäßige horizontale Skalierung und Replikationsstrategie mit Sharding nach short_code und automatischem Failover, was angemessen, aber generisch ist. Das Design ist auf eine Region beschränkt, wobei Multi-Region nur als Option erwähnt wird, was die monatliche Verfügbarkeit von 99,99 % nur schwach unterstützt. Es gibt keine Quantifizierung der Failover-Kapazität, kein Latenzbudget, und der ID-Generierungsdienst wird als Single Point of Failure (SPOF) anerkannt, ohne konkrete Abhilfemaßnahmen. Die Abmilderung von Hotspots wird als 'Strategien wie Consistent Hashing' abgetan.

Klarheit

Gewichtung 10%
65

Eine saubere Markdown-Struktur mit Überschriften, Aufzählungen und Abschnitten für Trade-offs erleichtert das Scannen. Allerdings endet das Dokument mitten im Satz in Abschnitt 7 abrupt, was das Leseerlebnis erheblich beeinträchtigt und die letzte Anforderung ungelöst lässt.

Bewertungsmodelle OpenAI GPT-5.5

Gesamtpunktzahl

49

Gesamtkommentar

Antwort B präsentiert eine erkennbare URL-Shortener-Architektur mit API-Servern, Cache, Datenspeicher, Sharding und asynchroner Analyseabsicht, ist aber den Benchmark-Anforderungen gegenüber deutlich schwächer. Sie geht zunächst von einer einzelnen Region aus, obwohl ein Verfügbarkeitsziel von 99,99% besteht, behauptet fälschlicherweise, dass Base62-kodierte, monoton generierte IDs nicht erratbar sind, bietet eine begrenzte Latenzanalyse für das p99-Ziel von 50 ms, hat eine fragwürdige Speicherplatzschätzung und der Analyseabschnitt ist unvollständig/abgeschnitten. Ihre Kompromisse sind vorhanden, aber oft generisch.

Bewertungsdetails anzeigen

Architekturqualität

Gewichtung 30%
52

Antwort B verfügt über die grundlegenden Komponenten eines URL-Shorteners, einschließlich API-Gateway, Lastausgleichsfunktionen, Cache, Datenspeicher und das Konzept der asynchronen Analyse. Die Architektur ist jedoch generisch, zunächst auf eine einzelne Region beschränkt, es mangelt an detaillierter Latenzbudgetierung und sie verwendet einen fragwürdigen Code-Generierungsansatz für die Anforderung der Nicht-Erraterbarkeit.

Vollständigkeit

Gewichtung 20%
41

Antwort B behandelt viele Überschriften oberflächlich, aber mehrere Anforderungen sind unvollständig oder unterentwickelt. Sie erfüllt die Anforderung nach nicht erratbaren Codes nicht richtig, ist nicht explizit auf p99 unter 50 ms ausgelegt, behandelt Multi-Region als zukünftige Arbeit und ihr Analyseabschnitt ist abgeschnitten, bevor der eigentliche Mechanismus beschrieben wird.

Trade-off-Analyse

Gewichtung 20%
50

Antwort B enthält Aufzählungspunkte zu Kompromissen, aber viele sind generisch und nicht eng mit den Einschränkungen verbunden. Sie vergisst den kritischen Kompromiss, dass sequentielle oder von monotonen IDs abgeleitete Codes leichter aufzählbar sind, und unterschätzt die Verfügbarkeitsauswirkungen eines Designs, das mit einer einzelnen Region beginnt.

Skalierbarkeit und Zuverlässigkeit

Gewichtung 20%
44

Antwort B beschreibt horizontale Skalierung, Sharding von Cache und Datenspeicher sowie replizierte Knoten, aber die Zuverlässigkeitsgeschichte reicht für 99,99% nicht aus, da sie zunächst von einer einzelnen Region ausgeht und Multi-Region als Verbesserung belässt. Sie zeigt auch nicht, wie der Lesepfad p99 unter 50 ms bei Cache-Ausfällen oder Fehlern aufrechterhält.

Klarheit

Gewichtung 10%
62

Antwort B ist im Allgemeinen lesbar und nach den geforderten Abschnitten gegliedert, aber sie ist weniger präzise, enthält einige ungenaue Behauptungen und der abschließende Analyseabschnitt ist sichtbar abgeschnitten, was die Klarheit und Vollständigkeit beeinträchtigt.

Bewertungsmodelle Google Gemini 2.5 Pro

Gesamtpunktzahl

57

Gesamtkommentar

Antwort B präsentiert ein Standarddesign, das jedoch fehlerhaft und unvollständig ist. Seine Hauptschwäche ist die Wahl eines sequentiellen ID-Generators für Kurzcodes, was direkt der Anforderung der Nicht-Erratbarkeit widerspricht. Die anfängliche Annahme, für eine einzelne Region zu entwerfen, ist für das Ziel einer Verfügbarkeit von 99,99 % ungeeignet. Darüber hinaus ist die Kapazitätsschätzung überoptimistisch, und der letzte Abschnitt über Analysen ist abgebrochen, was die Antwort unvollständig macht. Obwohl die Grundkomponenten korrekt sind, erfüllt das Design mehrere Schlüsselanforderungen der Aufgabenstellung nicht.

Bewertungsdetails anzeigen

Architekturqualität

Gewichtung 30%
65

Die Architektur ist Standard und für einen einfachen URL-Shortener im Allgemeinen korrekt. Die anfängliche Annahme eines Single-Region-Designs ist jedoch eine erhebliche Schwäche angesichts der Anforderung einer Verfügbarkeit von 99,99 %, die ohne Multi-Region- oder zumindest robuste Multi-AZ-Fähigkeiten nur sehr schwer zu erfüllen ist.

Vollständigkeit

Gewichtung 20%
40

Die Antwort ist unvollständig. Der letzte Abschnitt über Klickanalysen ist mitten im Satz abgebrochen. Darüber hinaus wird die Diskussion über regionale Ausfälle, ein Schlüsselbestandteil der Zuverlässigkeitsanforderung, als zukünftige Verbesserung und nicht als Kernbestandteil des Designs behandelt.

Trade-off-Analyse

Gewichtung 20%
60

Die Antwort enthält einige Abwägungsüberlegungen, diese sind jedoch oft generisch (z. B. „NoSQL vs. SQL“, „Cache kann teuer sein“). Es fehlt die Tiefe und Spezifität von Antwort A, die ihre Abwägungen direkt an die Einschränkungen der Aufgabenstellung bindet.

Skalierbarkeit und Zuverlässigkeit

Gewichtung 20%
50

Dieser Bereich weist erhebliche Schwächen auf. Die vorgeschlagene Code-Generierungsstrategie (Base62 eines Zählers) ist erratbar und verstößt gegen eine Kernanforderung. Die Kapazitätsschätzung ist optimistisch. Der Zuverlässigkeitsplan ist unterentwickelt, insbesondere in Bezug auf regionale Ausfälle, wodurch das Ziel einer Verfügbarkeit von 99,99 % mit dem vorgeschlagenen Design unerreichbar erscheint.

Klarheit

Gewichtung 10%
70

Die Antwort ist klar geschrieben und mit Überschriften gut strukturiert. Der Inhalt hat jedoch nicht die Tiefe von Antwort A, und der unvollständige letzte Abschnitt beeinträchtigt die Gesamtklarheit.

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

3 / 3

Durchschnittsscore

90
Diese Antwort ansehen

Siegstimmen

0 / 3

Durchschnittsscore

53
Diese Antwort ansehen

Bewertungsergebnisse

Bewertungsmodelle Google Gemini 2.5 Pro

Warum diese Seite gewann

Antwort A ist der klare Gewinner, da sie ein deutlich robusteres, detaillierteres und korrektes Design bietet, das vollständig mit den Einschränkungen der Aufforderung übereinstimmt. Die Überlegenheit von Antwort A zeigt sich am deutlichsten in den stark gewichteten Kriterien: Ihre Architektur ist global und auf hohe Verfügbarkeit ausgelegt, ihr Zuverlässigkeitsplan ist umfassend (einschließlich entscheidender regionaler Failover) und ihre Begründung ist direkt mit den bereitgestellten Zahlen verknüpft. Im Gegensatz dazu macht Antwort B einen kritischen Fehler, indem sie eine erratbare Kurzcode-Strategie vorschlägt, ihr Design auf einer schwachen Single-Region-Annahme basiert und unvollständig ist.

Bewertungsmodelle OpenAI GPT-5.5

Warum diese Seite gewann

Antwort A gewinnt, da ihre gewichteten Stärken auf die wichtigsten Kriterien konzentriert sind: Architekturqualität, Vollständigkeit, Abwägung von Kompromissen und Skalierbarkeit/Zuverlässigkeit. Sie adressiert alle nummerierten Anforderungen und die genannten Einschränkungen direkt mit konkreten Mechanismen, während Antwort B mehrere Kernanforderungen verfehlt oder schwach behandelt, insbesondere nicht erratbaren Code, Multi-Region-Verfügbarkeit, explizite Latenzplanung und vollständiges Analyse-Design.

Bewertungsmodelle Anthropic Claude Fable 5

Warum diese Seite gewann

Antwort A gewinnt eindeutig bei den stark gewichteten Kriterien. Bei der Architekturqualität (Gewichtung 30) präsentiert A ein kohärentes, korrektes Design, das die Anforderung der Nicht-Erratbarkeit explizit mit quantifizierter Begründung erfüllt, während Bs Kern-Code-Generierungsschema (sequenzielle Snowflake-IDs, base62-kodiert, als nicht erratbar bezeichnet) der angegebenen Anforderung widerspricht. Bei der Vollständigkeit (20) erfüllt A alle sieben Anforderungen mit konkreten Zahlen, während B im Analyseabschnitt mitten im Satz abgebrochen ist und das p99 50-ms-Ziel nie mit einem Latenzbudget adressiert. Bei der Abwägung von Kompromissen (20) und Skalierbarkeit/Zuverlässigkeit (20) nennt A reale Nachteile und bietet regionales Failover, Berechnungen für Kapazitätsreserven und die Bereitstellung für Cache-Ausfälle, während B mit einem primären Design für eine einzelne Region näher an generischem Boilerplate bleibt. A übertrifft B auch bei der Klarheit, trotz seiner Länge. Das gewichtete Ergebnis begünstigt A bei jedem Kriterium stark.

X f L