it-swarm.com.de

Wann sind Sie wirklich gezwungen, UUID als Teil des Designs zu verwenden?

Ich verstehe den Sinn von UUID nicht wirklich. Ich weiß, dass die Wahrscheinlichkeit einer Kollision effektiv null ist, aber effektiv null ist nicht einmal nahezu unmöglich.

Kann jemand ein Beispiel geben, bei dem Sie keine andere Wahl haben, als UUID zu verwenden? Von allen Anwendungen, die ich gesehen habe, kann ich ein alternatives Design ohne UUID sehen. Sicher, das Design ist vielleicht etwas komplizierter, aber zumindest hat es keine Ausfallwahrscheinlichkeit von null.

UUID riecht nach globalen Variablen für mich. Es gibt viele Möglichkeiten, wie globale Variablen für ein einfacheres Design sorgen, aber es ist nur ein fauler Entwurf.

106
Pyrolistical

Ich habe den UUID-Generator/Parser für Ruby geschrieben, daher halte ich mich für einigermaßen gut informiert. Es gibt vier Haupt-UUID-Versionen:

Version 4-UUIDs sind im Wesentlichen nur 16 Byte Zufallszahlen, die aus einem kryptographisch sicheren Zufallszahlengenerator abgerufen werden, wobei einige Bit-Twiddling-Werte verwendet werden, um die UUID-Version und -Variante zu identifizieren. Es ist äußerst unwahrscheinlich, dass diese zusammenstoßen, aber es kann vorkommen, dass ein PRNG verwendet wird oder wenn Sie zufällig wirklich, wirklich, wirklich, wirklich, wirklich Pech haben.

Version 5 und Version 3 UUIDs verwenden die SHA1- bzw. MD5-Hashfunktionen, um einen Namespace mit einem Teil bereits eindeutiger Daten zu kombinieren, um eine UUID zu generieren. So können Sie beispielsweise eine UUID aus einer URL erstellen. Kollisionen sind hier nur möglich, wenn auch die zugrunde liegende Hash-Funktion eine Kollision aufweist.

UUIDs der Version 1 sind die häufigsten. Sie verwenden die MAC-Adresse der Netzwerkkarte (die, sofern sie nicht gefälscht werden sollte, eindeutig sein sollte) sowie einen Zeitstempel und das übliche Bit-Twiddling, um die UUID zu generieren. Bei einer Maschine ohne MAC-Adresse werden die 6 Knoten-Bytes mit einem kryptographisch sicheren Zufallszahlengenerator generiert. Wenn zwei UUIDs so schnell generiert werden, dass der Zeitstempel mit dem vorherigen UUID übereinstimmt, wird der Zeitstempel um 1 erhöht. Kollisionen sollten nur dann auftreten, wenn eine der folgenden Bedingungen eintritt: Die MAC-Adresse wird gefälscht; Ein Computer, auf dem zwei verschiedene UUID-Anwendungen ausgeführt werden, erzeugt UUIDs im selben Moment. Zwei Maschinen ohne Netzwerkkarte oder ohne Zugriff auf die MAC-Adresse auf Benutzerebene erhalten dieselbe Zufallsknotenfolge und generieren UUIDs im selben Moment. Wir haben keine Bytes mehr, um den Zeitstempel darzustellen und zurück auf Null zu setzen.

Realistisch gesehen tritt keines dieser Ereignisse versehentlich im ID-Bereich einer einzelnen Anwendung auf. Wenn Sie keine IDs auf einer Internet-weiten Skala akzeptieren oder in einer nicht vertrauenswürdigen Umgebung, in der böswillige Personen im Falle einer ID-Kollision etwas Schlechtes tun können, ist dies nichts, worüber Sie sich Sorgen machen sollten. Es ist wichtig zu verstehen, dass wenn Sie die gleiche UUID der Version 4 wie ich generieren, dies in den meisten Fällen keine Rolle spielt. Ich habe die ID in einem völlig anderen ID-Bereich generiert. Meine Anwendung wird nie von der Kollision erfahren, so dass die Kollision keine Rolle spielt. In einem einzigen Anwendungsbereich ohne böswillige Akteure wird das gesamte Leben auf der Erde sogar vor einer Kollision, selbst bei einer UUID der Version 4, aussterben, selbst wenn Sie einige UUIDs pro Sekunde generieren.

Auch 2 ^ 64 * 16 entspricht 256 Exabyte. Wie in, müssten Sie IDs im Wert von 256 Exabyte speichern, bevor Sie eine 50% ige Chance für eine ID-Kollision in einem einzigen Anwendungsbereich hatten.

564
Bob Aman

Die Sache, die UUIDs Sie kaufen, ist sehr schwierig, ansonsten ist es, eine eindeutige Kennung zu erhalten ohne dass Sie sich mit einer zentralen Behörde beraten müssen . Das allgemeine Problem, so etwas ohne verwaltete Infrastruktur zu erhalten, ist das Problem, das die UUIDs lösen.

Ich habe gelesen, dass die Wahrscheinlichkeit einer UUID-Kollision laut Geburtstags-Paradoxon 50% beträgt, sobald 2 ^ 64 UUIDs generiert wurden. Nun ist 2 ^ 64 eine ziemlich große Zahl, aber eine 50% ige Kollisionswahrscheinlichkeit scheint viel zu riskant zu sein (z. B. wie viele UUIDs vorhanden sein müssen, bevor eine 5% ige Kollisionswahrscheinlichkeit besteht - selbst das scheint eine zu große Wahrscheinlichkeit zu sein). .

Das Problem bei dieser Analyse ist zweierlei:

  1. UUIDs sind nicht völlig zufällig - es gibt Hauptkomponenten der UUID, die zeit- und/oder ortsabhängig sind. Um eine echte Kollisionsgefahr zu haben, müssen die kollidierenden UUIDs zur selben Zeit von verschiedenen UUID-Generatoren generiert werden. Ich würde sagen, dass die Chance besteht, dass mehrere UUIDs gleichzeitig generiert werden, aber es gibt genug andere Gunk (einschließlich Positionsinformationen oder Zufallsbits), um die Ähnlichkeit einer Kollision zwischen dieser sehr kleinen Menge von UUIDs nahezu unmöglich zu machen .

  2. genau genommen müssen UUIDs nur unter den anderen UUIDs, mit denen sie verglichen werden können, eindeutig sein. Wenn Sie eine UUID generieren, die als Datenbankschlüssel verwendet werden soll, ist es egal, ob in einem bösen alternativen Universum die UUID zur Identifizierung einer COM-Schnittstelle verwendet wird. Genauso wie es keine Verwirrung verursacht, wenn jemand (oder etwas) namens "Michael Burr" auf Alpha-Centauri heißt.

67
Michael Burr

Alles hat eine Chance von null. Ich würde mich eher auf Probleme konzentrieren (d. H. Fast alles, was man sich vorstellen kann) als auf die Kollision von UUIDs

28
DanSingerman

Eine Betonung auf "vernünftig" oder, wie Sie sagen, "effektiv": Gut genug ist, wie die reale Welt funktioniert. Der Rechenaufwand, der erforderlich ist, um diese Lücke zwischen "praktisch einzigartig" und "wirklich einzigartig" zu schließen, ist enorm. Einzigartigkeit ist eine Kurve mit abnehmenden Erträgen. Irgendwann in dieser Kurve gibt es eine Grenze zwischen "einzigartig genug" ist noch erschwinglich, und dann krümmen wir uns SEHR steil. Die Kosten für das Hinzufügen von Einzigartigkeit werden ziemlich groß. Unendliche Einzigartigkeit hat unendliche Kosten.

UUID/GUID ist eine relativ schnelle und einfache Methode, um eine ID zu generieren, die vernünftigerweise als universell eindeutig angenommen werden kann. Dies ist sehr wichtig in vielen Systemen, die Daten aus zuvor nicht verbundenen Systemen integrieren müssen. Zum Beispiel: Wenn Sie über ein Content Management System verfügen, das auf zwei verschiedenen Plattformen ausgeführt wird, die Inhalte jedoch irgendwann von einem System in das andere importiert werden müssen. Sie möchten nicht, dass sich die IDs ändern, sodass Ihre Referenzen zwischen Daten aus System A erhalten bleiben. Sie möchten jedoch keine Kollisionen mit in System B erstellten Daten. Eine UUID löst dies.

15
Rex M

Es ist niemals absolut notwendig, eine UUID zu erstellen. Es ist jedoch praktisch, einen Standard zu haben, bei dem offline - Benutzer jeweils einen Schlüssel für etwas mit einer sehr geringen Kollisionswahrscheinlichkeit generieren können.

Dies kann bei der Auflösung der Datenbankreplikation usw. hilfreich sein.

Für online - Benutzer wäre es leicht, eindeutige Schlüssel für etwas ohne den Overhead oder die Möglichkeit einer Kollision zu generieren. Dies ist jedoch nicht die Aufgabe von UUIDs.

Wie auch immer, ein Wort zur Wahrscheinlichkeit einer Kollision aus der Wikipedia:

Um diese Zahlen in die richtige Perspektive zu setzen, besteht die jährliche Gefahr, getroffen zu werden von einem Meteoriten wird eine Chance auf 17 Milliarden geschätzt, das Äquivalent zu den Chancen, ein paar Dutzend Billionen UUIDs in einem Jahr zu schaffen, und ein Duplikat haben. Mit anderen Worten, erst nach der Generierung von 1 Milliarde UUIDs jede Sekunde für die nächsten 100 Jahre, die Wahrscheinlichkeit der Erstellung von Ein einziges Duplikat wäre etwa 50%.

14
John Gietzen

Es besteht auch eine Wahrscheinlichkeit, dass jedes Partikel in Ihrem Körper gleichzeitig durch den Stuhl tunnelt, auf dem Sie sitzen, und Sie werden plötzlich auf dem Boden sitzen.

Sorgen Sie sich darüber?

12
user21714

Ein klassisches Beispiel ist das Replizieren zwischen zwei Datenbanken.

DB (A) fügt einen Datensatz mit int ID 10 ein und gleichzeitig erstellt DB (B) einen Datensatz mit ID 10. 

Bei UUIDs wird dies nicht passieren, da sie nicht übereinstimmen. (Fast sicher) 

11
Johnno Nolan

Ich habe ein Schema zur Vermeidung von UUIDs. Richten Sie einen Server irgendwo ein und richten Sie ihn so ein, dass jedes Mal, wenn eine Software eine universell eindeutige Kennung wünscht, sie sich mit diesem Server in Verbindung setzen und diese verteilen. Einfach!

Abgesehen davon gibt es einige echte praktische Probleme, auch wenn wir geradezu böswillig sind. Insbesondere kann dieser Server aus dem Internet ausfallen oder nicht mehr erreichbar sein. Der Umgang mit Serverausfällen erfordert eine Replikation, und das ist sehr schwierig , um richtig zu werden (in der Literatur zum Paxos-Algorithmus wird erläutert, warum die Konsensbildung unangenehm ist) und ziemlich langsam. Wenn außerdem alle Server von einem bestimmten Teil des 'Netzes aus nicht erreichbar sind, können none der Clients, die mit diesem Subnetz verbunden sind, alles tun, da alle auf neue IDs warten.

Verwenden Sie also einen einfachen probabilistischen Algorithmus, um sie zu generieren, der wahrscheinlich nicht während der gesamten Lebensdauer der Erde ausfällt, oder (finanzieren und bauen Sie) eine große Infrastruktur, die eine Bereitstellungs-PITA sein wird und häufige Fehler aufweist. Ich weiß, für wen ich gehen würde.

5
Donal Fellows

Wenn Sie nur die Alternativen betrachten, z. Für eine einfache Datenbankanwendung, die die Datenbank jedes Mal abfragen muss, bevor Sie ein neues Objekt erstellen, werden Sie schnell feststellen, dass die Verwendung der UUID die Komplexität Ihres Systems effektiv reduzieren kann. Zugegeben - Wenn Sie int-Schlüssel verwenden, werden 32 Bit verwendet, die in einem Viertel der 128-Bit-UUID gespeichert werden. Zugegeben - UUID-Generierungsalgorithmen verbrauchen mehr Rechenleistung als das einfache Erhöhen einer Anzahl. Aber wen interessiert das schon? Der Aufwand für das Verwalten einer "Autorität" für das Zuweisen ansonsten eindeutiger Nummern überwiegt je nach dem von Ihnen beabsichtigten Eindeutigkeits-ID-Bereich leicht um Größenordnungen.

4
Mirko Klemm

Auf UUID == faules Design

Ich stimme nicht zu, dass es darum geht, Ihre Kämpfe auszuwählen. Wenn eine doppelte UUID statistisch nicht möglich ist und die Mathematik bewiesen ist, warum dann Sorge? Es ist nicht praktikabel, Zeit für das Design Ihres kleinen N UUID-Generierungssystems zu verwenden. Es gibt immer ein Dutzend anderer Möglichkeiten, wie Sie Ihr System verbessern können.

3
Johnno Nolan

ich bekomme nicht die ganze Diskussion über die Wahrscheinlichkeit einer Kollision. Kollision ist mir egal. Ich interessiere mich aber für Leistung. 

https://dba.stackexchange.com/a/119129/33649

UUIDs sind ein Performance-Desaster für sehr große Tabellen. (200K-Zeilen sind Nicht "sehr groß".)

Ihre Nummer 3 ist wirklich schlecht, wenn der Zeichensatz utf8 - CHAR (36) .__ ist. belegt 108 Bytes!

UUIDs (GUIDs) sind sehr "zufällig". Verwendung als UNIQUE oder als Der Primärschlüssel für große Tabellen ist sehr ineffizient. Das ist wegen Sie müssen jedes Mal, wenn Sie eine neue UUID einfügen, um die Tabelle/den Index springen. oder SELECT per UUID. Wenn die Tabelle/der Index zu groß ist, um in den Cache zu passen (Siehe innodb_buffer_pool_size, der kleiner sein muss als der Arbeitsspeicher (normalerweise 70%)), kann die UUID 'next' nicht zwischengespeichert werden, daher eine langsame Festplatte schlagen. Wenn die Tabelle/der Index 20 Mal so groß ist wie der Cache, ist nur 1/20 (5%) der Treffer werden zwischengespeichert - Sie sind E/A-gebunden.

Verwenden Sie also keine UUIDs, wenn nicht

sie haben "kleine" Tabellen oder brauchen sie wirklich, weil sie eindeutige IDs von verschiedenen Orten (und haben noch keine andere Möglichkeit herausgefunden.). Weitere Informationen zu UUIDs: http://mysql.rjweb.org/doc.php/uuid (It Enthält Funktionen zum Konvertieren zwischen Standard-UUIDs mit 36 ​​Zeichen und BINARY (16).)

Ein UNIQUE AUTO_INCREMENT und eine UNIQUE UUID in derselben Tisch ist eine Verschwendung.

Wenn ein INSERT auftritt, müssen alle eindeutigen/Primärschlüssel auf .__ überprüft werden. Duplikate. Für die Anforderung von InnoDB ist entweder ein eindeutiger Schlüssel ausreichend einen primären Schlüssel zu haben. BINARY (16) (16 Bytes) ist etwas sperrig (ein Argument dagegen, dass es die PK ist), aber nicht so schlimm. Die Sperrigkeit ist wichtig, wenn Sie sekundäre Schlüssel haben. InnoDB greift lautlos die PK auf das Ende jedes Sekundärschlüssels. Die Hauptstunde hier ist zu Minimieren Sie die Anzahl der Sekundärschlüssel, insbesondere für sehr große Tische. Zum Vergleich: INT UNSIGNED besteht aus 4 Bytes im Bereich 0..4 Milliarde. BIGINT ist 8 Byte.

2
Toskan

Für diejenigen, die sagen, dass UUIDs schlecht designt sind, weil sie könnten (mit einer lächerlich geringen Wahrscheinlichkeit) kollidieren, während Ihre von der Datenbank generierten Schlüssel nicht ... Sie wissen, dass menschliches Versagen eine Kollision auf Ihrem Computer verursachen kann Von der Datenbank generierte Schlüssel, die aufgrund eines nicht vorhergesehenen Bedarfs erstellt wurden, sind bei Weitem weitaus höher als die Wahrscheinlichkeit einer UUID4-Kollision. Wir wissen dass, wenn die Datenbank neu erstellt wird, die IDs wieder bei 1 beginnen, und wie viele von uns mussten eine Tabelle neu erstellen, als wir sicher waren, dass wir dies niemals brauchen würden? Ich würde mein Geld in die UUID-Sicherheit stecken, wenn mit Unbekannten jeden Tag etwas schief geht.

1
Iain Duncan

Bei Verwendung des Algorithmus der Version 1 scheint es unmöglich zu sein, unter der Bedingung, dass weniger als 10 UUIDs pro Millisekunde von derselben MAC-Adresse generiert werden, eine Kollision zu sein 

Konzeptionell ist das Original (Version 1) Generierungsschema für UUIDs war verketten Sie die UUID-Version mit der MAC-Adresse des Computers, der .__ lautet. Generieren der UUID und mit der Anzahl von 100-Nanosekunden-Intervallen seit der Verabschiedung des Gregorianers Kalender im Westen. In der Praxis wird der Der tatsächliche Algorithmus ist komplizierter . Dieses Schema wurde in .__ kritisiert. dass es nicht ausreichend "undurchsichtig" ist; es offenbart sowohl die Identität des Computer, der die UUID und .__ generiert hat. die Zeit, zu der es so war.

Jemand korrigiert mich, wenn ich falsch verstanden habe, wie es funktioniert

1
Davy8

Abgesehen von den Fällen, in denen Sie die API eines anderen Benutzers verwenden müssen, die eine UUID erfordert, gibt es natürlich immer eine andere Lösung. Aber werden diese Alternativen alle die Probleme der UUIDs lösen? Werden Sie am Ende weitere Schichten von Hacks hinzufügen, die jeweils ein anderes Problem lösen, wenn Sie alle gleichzeitig lösen könnten?

Ja, UUIDs können theoretisch kollidieren. Wie andere bereits bemerkt haben, ist es unwahrscheinlich, dass es sich nicht lohnt, darüber nachzudenken. Es ist noch nie passiert und wird es wahrscheinlich auch nie tun. Vergiss es.

Der "naheliegendste" Weg, um Kollisionen zu vermeiden, besteht darin, dass ein einzelner Server für jede Einfügung eindeutige IDs generiert, was offensichtlich zu schwerwiegenden Leistungsproblemen führt und das Problem der Offline-Generierung überhaupt nicht löst. Hoppla.

Die andere "offensichtliche" Lösung ist eine zentrale Instanz, die im Voraus Blöcke mit eindeutigen Nummern austeilt. Dies ist im Wesentlichen das, was die UUID V1 unter Verwendung der MAC-Adresse der Erzeugungsmaschine (über die IEEE-OUI) tut. Doppelte MAC-Adressen treten jedoch auf, weil jede zentrale Instanz letztendlich fehlerhaft ist. In der Praxis ist dies viel wahrscheinlicher als eine UUID-V4-Kollision. Hoppla.

Das beste Argument gegen die Verwendung von UUIDs ist, dass sie "zu groß" sind, aber ein (erheblich) kleineres Schema wird unweigerlich die interessantesten Probleme nicht lösen. Die Größe der UUIDs ist eine inhärente Nebenwirkung ihres Nutzens bei der Lösung genau dieser Probleme.

Es ist möglich, dass Ihr Problem nicht groß genug ist, um das zu bieten, was UUIDs bieten. In diesem Fall können Sie gerne etwas anderes verwenden. Wenn Ihr Problem jedoch unerwartet zunimmt (und die meisten tun es), werden Sie später umsteigen - und sich selbst dafür einsetzen, dass Sie es nicht in erster Linie verwenden. Warum Design for Failure, wenn es genauso einfach für Erfolg zu entwerfen ist?

0
StephenS

Bei meinem letzten Job bekamen wir Objekte von Dritten, die eindeutig mit UUID identifiziert wurden. Ich habe eine UUID-> Long Integer-Lookup-Tabelle eingefügt und Long Integer als Primärschlüssel verwendet, weil es so viel schneller war.

0
Paul Tomblin