Systemdesign des URL-Verkürzungsdienstes

Okt 2, 2021
admin

Wenn wir einen neuen Schlüssel brauchen, können wir eine der bereits generierten IDs nehmen. Dieser Ansatz kann die Dinge beschleunigen, da wir bei einer neuen Anfrage keine ID erstellen und ihre Einzigartigkeit sicherstellen müssen usw. UGS stellt sicher, dass alle IDs eindeutig sind, und sie können in einer Datenbank gespeichert werden, so dass die IDs nicht jedes Mal neu generiert werden müssen.

Da wir ein Byte benötigen, um ein Zeichen zu speichern, können wir alle diese Schlüssel speichern in:

6 (Zeichen) * 68.7B (eindeutige Schlüssel) ~= 412 GB.

★Verfügbarkeit &Zuverlässigkeit:

Wenn wir eine Kopie von UGS behalten, ist das ein Single Point of Failure. Daher müssen wir eine Kopie von UGS erstellen. Wenn der primäre Server ausfällt, kann der sekundäre Server die Anfragen der Benutzer bearbeiten.

Jeder UGS-Server kann einige Schlüssel aus der Schlüssel-DB zwischenspeichern. Das kann die Dinge beschleunigen. Aber wir müssen vorsichtig sein; wenn ein Server stirbt, bevor er alle Schlüssel verbraucht hat, werden wir diese Schlüssel verlieren. Aber wir können davon ausgehen, dass dies akzeptabel ist, da wir fast 68B eindeutige Schlüssel mit sechs Buchstaben haben.

Um die Verfügbarkeit zu gewährleisten, müssen wir sicherstellen, dass ein einzelner Fehlerpunkt im System entfernt wird. Die Replikation von Daten beseitigt eine einzelne Fehlerquelle und bietet eine Datensicherung. Um die Zuverlässigkeit des Datenbankservers zu gewährleisten, können wir mehrere Replikationen durchführen. Und für einen unterbrechungsfreien Dienst benötigen auch andere Server Kopien.

★DataStorage:

In diesem System müssen wir Milliarden von Datensätzen speichern. Jedes Objekt, das wir speichern, ist möglicherweise weniger als 1 KB groß. Die Daten einer URL stehen in keinem Zusammenhang mit anderen. Wir können also eine NoSQL-Datenbank wie Cassandra, DynamoDB usw. verwenden. Eine NoSQL-Datenbank wäre einfacher zu skalieren, was eine unserer Anforderungen ist.

★ Skalierbarkeit:

Um Milliarden von URLs zu unterstützen, müssen wir unsere Datenbank partitionieren, um unsere Daten auf verschiedene DB-Server aufzuteilen und zu speichern.

i) Wir können die Datenbank auf der Grundlage des ersten Buchstabens des Hash-Schlüssels partitionieren. Wir können Schlüssel, die mit ‚A‘ beginnen, auf einem Server ablegen, ‚B‘ auf einem anderen Server. Dies wird als bereichsbasierte Partitionierung bezeichnet.

Das Problem bei diesem Ansatz ist, dass er zu einer unausgewogenen Partitionierung führen kann. Zum Beispiel gibt es nur sehr wenige Wörter, die mit ‚Z‘ beginnen. Andererseits haben wir vielleicht zu viele URLs, die mit dem Buchstaben ‚E‘ beginnen.

Wir können weniger häufig vorkommende Buchstaben in einer Datenbankpartition zusammenfassen.

ii) Wir können auch auf der Grundlage des Hash der gespeicherten Objekte partitionieren. Wir können den Hash des Schlüssels nehmen, um die Partition zu bestimmen, in der wir das Datenobjekt speichern können. Die Hash-Funktion generiert eine Servernummer, und wir speichern den Schlüssel auf diesem Server. Durch dieses Verfahren kann die Verteilung zufälliger gestaltet werden. Dies ist die Hash-basierte Partitionierung.

Wenn dieser Ansatz immer noch zu überladenen Partitionen führt, müssen wir konsistentes Hashing verwenden.

★ Cache:

Wir können URLs, auf die die Benutzer häufig zugreifen, im Cache speichern. Die UGS-Server können vor der Abfrage der Datenbank prüfen, ob der Cache die gewünschte URL enthält. Dann braucht er die Abfrage nicht erneut durchzuführen.

Was passiert, wenn der Cache voll ist? Wir können einen älteren, nicht verwendeten Link durch eine neuere oder beliebte URL ersetzen. Wir können für unser System die LRU-Richtlinie (Least Recently Used) zur Cache-Evakuierung wählen. Bei dieser Richtlinie wird die am wenigsten genutzte URL zuerst entfernt.

★ Lastausgleich:

Wir können eine Lastausgleichsschicht an verschiedenen Stellen in unserem System hinzufügen, vor dem URL-Verkürzungsserver, der Datenbank und den Cache-Servern.

Wir können einen einfachen Round-Robin-Ansatz für die Verteilung von Anfragen verwenden. Bei diesem Ansatz verteilt LB die eingehenden Anfragen gleichmäßig auf die Backend-Server. Dieser Ansatz von LB ist einfach zu implementieren. Wenn ein Server tot ist, wird LB aufhören, Daten an ihn zu senden.

Problem: Wenn ein Server überlastet ist, wird LB bei diesem Ansatz nicht aufhören, neue Anfragen an diesen Server zu senden. Vielleicht brauchen wir später einen intelligenten LB.

★ Linkablauf nach einer bestimmten Dauer:

Wenn die Ablaufzeit für eine URL erreicht ist, was würde dann mit dem Link passieren?

Wir können in unseren Datenspeichern suchen und sie entfernen. Das Problem dabei ist, dass wir unsere Datenbank stark belasten würden, wenn wir nach abgelaufenen Links suchen würden, um sie aus unserem Datenspeicher zu entfernen.

Wir können es auch anders machen. Wir können abgelaufene Links langsam und regelmäßig entfernen. Selbst wenn einige tote Links länger leben, sollten sie niemals an die Benutzer zurückgegeben werden.

Wenn ein Benutzer versucht, auf einen abgelaufenen Link zuzugreifen, können wir den Link entfernen und dem Benutzer eine Fehlermeldung zurückgeben. In regelmäßigen Abständen kann ein Bereinigungsprozess durchgeführt werden, um abgelaufene Links aus unserer Datenbank zu entfernen. Da der Speicherplatz immer billiger wird, können einige Links dort verbleiben, auch wenn wir die Bereinigung versäumen.

Nach dem Entfernen des Links können wir ihn zur Wiederverwendung wieder in unsere Datenbank aufnehmen.

★ Sicherheit:

Wir können die Zugriffsart (öffentlich/privat) mit jeder URL in der Datenbank speichern. Wenn ein Benutzer versucht, auf eine URL zuzugreifen, für die er keine Berechtigung hat, kann das System eine Fehlermeldung (HTTP 401) zurückschicken.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.