Was sind UUIDs und warum sind sie nützlich?

0
742
Stokkete/Shutterstock.com

Ein Universally Unique Identifier (UUID) ist eine spezifische Form der Kennung, die für die meisten praktischen Zwecke sicher als eindeutig angesehen werden kann. Zwei korrekt generierte UUIDs haben eine praktisch vernachlässigbare Chance, identisch zu sein, selbst wenn sie in zwei verschiedenen Umgebungen von verschiedenen Parteien erstellt wurden. Aus diesem Grund gelten UUIDs als universell einzigartig.

In diesem Artikel betrachten wir die Eigenschaften von UUIDs, wie ihre Eindeutigkeit funktioniert und die Szenarien, in denen sie die Ressourcenidentifikation vereinfachen können. Obwohl wir uns UUIDs aus der allgemeinen Perspektive von Software nähern werden, die mit Datenbankeinträgen interagiert, sind sie allgemein auf jeden Anwendungsfall anwendbar, bei dem eine dezentrale eindeutige ID-Generierung erforderlich ist.

Was ist eigentlich eine UUID?

Eine UUID ist einfach ein Wert, den Sie sicher als eindeutig behandeln können. Das Kollisionsrisiko ist so gering, dass Sie es vernünftigerweise ganz ignorieren können. UUIDs werden möglicherweise mit anderen Begriffen bezeichnet (GUID oder Globally Unique Identifier ist die bevorzugte Semantik von Microsoft), aber Bedeutung und Wirkung bleiben gleich.

Eine echte UUID ist eine eindeutige Kennung, die durch ein standardisiertes Format generiert und dargestellt wird. Gültige UUIDs werden durch RFC 4122 definiert; diese Spezifikation beschreibt die Algorithmen, die verwendet werden können, um UUIDs zu generieren, die die Eindeutigkeit über Implementierungen hinweg bewahren, ohne eine zentrale ausstellende Autorität.

Der RFC umfasst fünf verschiedene Algorithmen, die jeweils einen anderen Mechanismus verwenden, um einen Wert zu erzeugen. Hier ist eine kurze Zusammenfassung der verfügbaren “Versionen”:

  • Version 1 – Zeitbasiert– Kombiniert einen Zeitstempel, eine Taktsequenz und einen Wert, der für das generierende Gerät (normalerweise seine MAC-Adresse) spezifisch ist, um eine Ausgabe zu erzeugen, die zu diesem Zeitpunkt für diesen Host eindeutig ist.
  • Version 2 – DCE-Sicherheit – Diese Version wurde als Weiterentwicklung von Version 1 für die Verwendung mit Distributed Computing Environment (DCE) entwickelt. Es ist nicht weit verbreitet.
  • Version 3 – Namensbasiert (MD5)– MD5 hasht einen “Namespace” und einen “Namen” um einen Wert zu erstellen, der für diesen Namen innerhalb des Namespace eindeutig ist. Das Generieren einer anderen UUID mit demselben Namensraum und Namen erzeugt eine identische Ausgabe, sodass diese Methode reproduzierbare Ergebnisse liefert.
  • Version 4 – Zufällig – Die meisten modernen Systeme entscheiden sich tendenziell für UUID v4, da es die Quelle von Zufalls- oder Pseudozufallszahlen des Hosts verwendet, um seine Werte auszugeben. Die Wahrscheinlichkeit, dass dieselbe UUID zweimal erzeugt wird, ist praktisch vernachlässigbar.
  • Version 5 – Namensbasiert (SHA-1)– Dies ähnelt Version 3, aber es verwendet den stärkeren SHA-1-Algorithmus, um den eingegebenen Namensraum und Namen zu hashen.

Werbung

Obwohl der RFC die Algorithmen als Versionen bezeichnet, trifft dies zu bedeutet nicht, dass Sie immer Version 5 verwenden sollten, weil es anscheinend die neueste ist. Die zu wählende hängt von Ihrem Anwendungsfall ab; In vielen Szenarien wird v4 aufgrund seiner zufälligen Natur ausgewählt. Dies macht es zum idealen Kandidaten für einfache “geben Sie mir eine neue Kennung” Szenarien.

Generierungsalgorithmen geben eine 128-Bit-Ganzzahl ohne Vorzeichen aus. UUIDs werden jedoch häufiger als hexadezimale Zeichenfolgen angesehen und können auch als binäre Folge von 16 Zeichen gespeichert werden. Hier ist ein Beispiel für eine UUID-Zeichenfolge:

16763be4-6022-406e-a950-fcd5018633ca

Der Wert wird als fünf Gruppen alphanumerischer Zeichen dargestellt, die durch Bindestriche getrennt sind. Die Bindestriche sind kein obligatorischer Bestandteil der Zeichenfolge; Ihre Anwesenheit ist auf historische Details der UUID-Spezifikation zurückzuführen. Sie erleichtern auch die Wahrnehmung des Identifikators für das menschliche Auge.

UUID-Anwendungsfälle

Der Hauptanwendungsfall für UUIDs ist die dezentrale Generierung von Uniques Kennungen. Sie können die UUID überall generieren und sicher als eindeutig betrachten, ob sie aus Ihrem Backend-Code, einem Client-Gerät oder Ihrer Datenbank-Engine stammt.

UUIDs vereinfachen die Bestimmung und Aufrechterhaltung der Objektidentität über getrennte Umgebungen hinweg. In der Vergangenheit verwendeten die meisten Anwendungen ein automatisch inkrementierendes Integer-Feld als Primärschlüssel. Wenn Sie ein neues Objekt erstellen, können Sie seine ID erst kennen, nachdem es in die Datenbank eingefügt wurde. Mit UUIDs können Sie die Identität viel früher in Ihrer Anwendung bestimmen.

Hier ist eine grundlegende PHP-Demo, die den Unterschied demonstriert. Schauen wir uns zuerst das ganzzahlbasierte System an:

Klasse BlogPost { öffentliche Funktion __konstruieren( öffentlich schreibgeschützt ?int $Id, öffentlich schreibgeschützt Zeichenfolge $Headline, öffentlich schreibgeschützt ?AuthorCollection $Authors=null) {} }   #[POST("/posts")]-Funktion createBlogPost(HttpRequest $Request) : ungültig { $headline = $Anfrage -> getField("Überschrift"); $blogPost = neuer BlogPost(null, $headline); } Werbung

Wir müssen die $Id-Eigenschaft mit null initialisieren, da wir ihre tatsächliche ID erst kennen können, nachdem sie in der Datenbank gespeichert wurde. Das ist nicht ideal – $Id sollte nicht wirklich nullable sein und erlaubt es, dass BlogPost-Instanzen in einem unvollständigen Zustand existieren.

Der Wechsel zu UUIDs behebt das Problem:

Klasse BlogPost { öffentliche Funktion __konstruieren( öffentlicher schreibgeschützter String $Uuid, öffentlicher schreibgeschützter String $Headline, öffentlicher schreibgeschützter ?AuthorCollection $Authors=null) {} }   #[POST("/posts")]-Funktion createBlogPost(HttpRequest $Request) : ungültig { $headline = $Anfrage -> getField("Überschrift"); $blogPost = neuer BlogPost("16763be4-…", $headline); }

Beitragskennungen können jetzt innerhalb der Anwendung generiert werden, ohne doppelte Werte zu riskieren. Dadurch wird sichergestellt, dass Objektinstanzen immer einen gültigen Zustand darstellen und keine umständlichen nullable ID-Eigenschaften benötigen. Das Modell erleichtert auch den Umgang mit Transaktionslogik; Untergeordnete Datensätze, die einen Verweis auf ihren übergeordneten Datensatz benötigen (z. B. die Autorenzuordnungen unserer Posts), können sofort eingefügt werden, ohne dass ein Datenbank-Roundtrip erforderlich ist, um die ID abzurufen, die dem übergeordneten Datensatz zugewiesen wurde.

In Zukunft wird Ihre Bloganwendung möglicherweise mehr Logik in den Client verschieben. Vielleicht erhält das Front-End Unterstützung für die vollständige Offline-Entwurfserstellung, wodurch effektiv BlogPost-Instanzen erstellt werden, die vorübergehend auf dem Gerät des Benutzers gespeichert werden. Jetzt könnte der Client die Post-UUID generieren und an den Server übertragen, wenn die Netzwerkverbindung wiederhergestellt ist. Wenn der Client anschließend die Serverkopie des Entwurfs abrufen würde, könnte er ihn mit jedem verbleibenden lokalen Zustand abgleichen, da die UUID bereits bekannt wäre.

UUIDs helfen Ihnen auch dabei, Daten aus verschiedenen Quellen zu kombinieren . Das Zusammenführen von Datenbanktabellen und Caches, die ganzzahlige Schlüssel verwenden, kann mühsam und fehleranfällig sein. UUIDs bieten Eindeutigkeit nicht nur innerhalb von Tabellen, sondern auf der Ebene des gesamten Universums. Dies macht sie zu viel besseren Kandidaten für replizierte Strukturen und Daten, die häufig zwischen verschiedenen Speichersystemen verschoben werden.

Warnhinweise, wenn UUIDs auf Datenbanken treffen

h2>

Die Vorteile von UUIDs sind ziemlich überzeugend. Es gibt jedoch einige Fallstricke, auf die Sie achten müssen, wenn Sie sie in realen Systemen verwenden. Ein wichtiger Faktor für ganzzahlige IDs ist, dass sie einfach zu skalieren und zu optimieren sind. Datenbank-Engines können problemlos eine Liste von Zahlen indizieren, sortieren und filtern, die nur in eine Richtung gehen.

Dasselbe gilt nicht für UUIDs. Zunächst einmal sind UUIDs viermal größer als ganze Zahlen (36 Bytes gegenüber 4 Bytes); Bei großen Datensätzen kann dies an sich schon eine wichtige Überlegung sein. Die Werte sind auch viel schwieriger zu sortieren und zu indizieren, insbesondere im Fall der häufigsten zufälligen UUIDs. Ihre zufällige Natur bedeutet, dass sie keine natürliche Ordnung haben. Dies beeinträchtigt die Indizierungsleistung, wenn Sie eine UUID als Primärschlüssel verwenden.

Werbung

Diese Probleme können sich in einer gut normalisierten Datenbank verschlimmern, die stark von Fremdschlüsseln Gebrauch macht. Jetzt haben Sie möglicherweise viele relationale Tabellen, von denen jede Verweise auf Ihre 36-Byte-UUIDs enthält. Schließlich könnte der zusätzliche Arbeitsspeicher, der zum Ausführen von Verknüpfungen und Sortierungen benötigt wird, erhebliche Auswirkungen auf die Leistung Ihres Systems haben.

Sie können die Probleme teilweise entschärfen, indem Sie Ihre UUIDs als Binärdaten speichern. Das bedeutet eine BINARY(16)-Spalte anstelle von VARCHAR(36). Einige Datenbanken wie PostgreSQL enthalten einen integrierten UUID-Datentyp; andere wie MySQL haben Funktionen, die einen UUID-String in seine binäre Darstellung umwandeln können und umgekehrt. Dieser Ansatz ist effizienter, aber denken Sie daran, dass Sie immer noch zusätzliche Ressourcen zum Speichern und Auswählen Ihrer Daten verwenden werden.

Eine effektive Strategie kann darin bestehen, ganze Zahlen als Ihre Primärschlüssel beizubehalten, aber ein zusätzliches UUID-Feld für hinzuzufügen die Referenz Ihrer Bewerbung. Relationale Linktabellen könnten IDs verwenden, um die Leistung zu verbessern, während Ihr Code Objekte der obersten Ebene mit UUIDs abruft und einfügt. Es hängt alles von Ihrem System, seiner Größe und Ihren Prioritäten ab: Wenn Sie eine dezentrale ID-Generierung und unkomplizierte Datenzusammenführungen benötigen, sind UUIDs die beste Option, aber Sie müssen die Kompromisse erkennen.

Zusammenfassung

UUIDs sind eindeutige Werte, die Sie sicher für die dezentrale Identitätsgenerierung verwenden können. Kollisionen sind möglich, sollten aber so selten sein, dass sie nicht berücksichtigt werden können. Wenn Sie ein ganzes Jahrhundert lang eine Milliarde UUIDs pro Sekunde generieren würden, würde die Wahrscheinlichkeit, auf ein Duplikat zu stoßen, bei etwa 50 % liegen, vorausgesetzt, es wäre genügend Entropie vorhanden.

Sie können UUIDs verwenden, um die Identität unabhängig von Ihrer Datenbank festzustellen, bevor eine Einfügung erfolgt. Dies vereinfacht den Code auf Anwendungsebene und verhindert, dass falsch identifizierte Objekte in Ihrem System vorhanden sind. UUIDs unterstützen auch die Datenreplikation, indem sie Eindeutigkeit unabhängig von Datenspeicher, Gerät oder Umgebung garantieren, im Gegensatz zu herkömmlichen ganzzahligen Schlüsseln, die auf Tabellenebene arbeiten.

Während UUIDs heute in der Softwareentwicklung allgegenwärtig sind, sind sie nicht perfekt Lösung. Neulinge neigen dazu, sich auf die Möglichkeit von Kollisionen zu fixieren, aber dies sollte nicht Ihre Hauptüberlegung sein, es sei denn, Ihr System ist so empfindlich, dass die Eindeutigkeit garantiert werden muss.

Werbung

Die offensichtlichere Herausforderung für die meisten Entwickler betrifft die Speichern und Abrufen von generierten UUIDs. Die naive Verwendung von VARCHAR(36) (oder das Entfernen der Bindestriche und die Verwendung von VARCHAR(32)) könnte Ihre Anwendung im Laufe der Zeit lahmlegen, da die meisten Datenbankindizierungsoptimierungen unwirksam sind. Informieren Sie sich über die integrierten UUID-Handhabungsfunktionen Ihres Datenbanksystems, um sicherzustellen, dass Sie die bestmögliche Leistung aus Ihrer Lösung herausholen.