Wie gut ist Javas UUID.randomUUID?

311

Ich weiß, dass randomisierte UUIDs theoretisch eine sehr, sehr, sehr geringe Kollisionswahrscheinlichkeit haben, aber ich frage mich in der Praxis, wie gut Java randomUUID()ist, wenn es nicht zu Kollisionen kommt. Hat jemand Erfahrungen zu teilen?

Alvin
quelle
10
Nach meiner Erfahrung habe ich noch nie eine Kollision gesehen ;-)
Thilo
4
Die Algorithmen sind in RFC1422 angegeben: ietf.org/rfc/rfc4122.txt
skaffman
8
@skaffman: Der RFC sagt absolut nichts über den Algorithmus aus, der zum Generieren der zufälligen Ziffern verwendet wird.
Michael Borgwardt
4
Da dies eine offenere Frage ist, werde ich wahrscheinlich keine Antwort als die richtige Antwort markieren. Stattdessen werde ich für jede der Antworten, die ich für gut halte, eine Stimme abgeben :)
Alvin
5
Aus Wikipedia: ... Mit anderen Worten, erst nachdem in den nächsten 100 Jahren pro Sekunde 1 Milliarde UUIDs generiert wurden, würde die Wahrscheinlichkeit, nur ein Duplikat zu erstellen, bei etwa 50% liegen.
MaVRoSCy

Antworten:

168

UUID verwendet java.security.SecureRandom, die "kryptografisch stark" sein soll. Während die tatsächliche Implementierung nicht angegeben ist und zwischen JVMs variieren kann (was bedeutet, dass alle konkreten Aussagen nur für eine bestimmte JVM gültig sind), muss die Ausgabe einen statistischen Zufallszahlengeneratortest bestehen.

Es ist immer möglich, dass eine Implementierung subtile Fehler enthält, die all dies ruinieren (siehe OpenSSH-Fehler bei der Schlüsselgenerierung), aber ich glaube, es gibt keinen konkreten Grund, sich über die Zufälligkeit von Java-UUIDs Sorgen zu machen.

Michael Borgwardt
quelle
34
"Es ist immer möglich, dass eine Implementierung subtile Fehler enthält ..." - Oder (Zinnfolienhut aufsetzen) ... absichtlich subtile Fehler. <:-)
Stephen C
25
Die kryptografische Stärke ist für die Frage der Kollisionen völlig irrelevant.
osa
14
@osa: Keine Kollisionen zu erzeugen (mehr als von perfekter Zufälligkeit zu erwarten), ist so ziemlich die niedrigste Qualitätsanforderung für ein RNG, während die kryptografische Stärke die höchste ist. Mit anderen Worten, ein kryptografisch starkes RNG wird definitiv nicht mehr Kollisionen als erwartet erzeugen.
Michael Borgwardt
3
Es kann jedoch nützlich sein zu beachten, dass Sie wahrscheinlich viele, viele Kollisionen bekommen , wenn Sie beispielsweise eine JVM ausführen, die UUIDs in blogs.vmware.com/cto/… ausgibt . Alle Software-RNGs sind PRNGs und letztendlich nur so gut wie ihre Entropiequelle. Zwei PRNGs, die identisch gesetzt werden, verhalten sich ebenfalls identisch. Dies kann überraschend häufig bei konsistenten, genau duplizierten Server-Setups und Startprozeduren vorkommen.
user508633
@ user508633: Ich würde tatsächlich erwarten, dass in diesem speziellen Fall eine Kollisionsrate von 100% erreicht wird, aber es ist in der Tat ein sehr spezifischer Fall, der weit über "konsistente, exakt doppelte Server-Setups und Startprozeduren" hinausgeht. Ich bin mir ziemlich sicher, dass Sie keine erhöhten Kollisionsraten erhalten würden, wenn Sie lediglich eine VM klonen und normal ausführen würden. Das Self-Seeding von SecureRandom versucht ziemlich hart, eine echte Entropie zu erreichen, bis die Ausführung blockiert wird, wenn keine gefunden wird: seancassidy.me/wiggle-the-mouse-to-fix-the-test.html
Michael Borgwardt
114

Wikipedia hat eine sehr gute Antwort http://en.wikipedia.org/wiki/Universally_unique_identifier#Collisions

Die Anzahl der zufälligen UUIDs der Version 4, die generiert werden müssen, um eine 50% ige Wahrscheinlichkeit für mindestens eine Kollision zu haben, beträgt 2,71 Billionen, berechnet wie folgt:

...

Diese Zahl entspricht einer Generierung von 1 Milliarde UUIDs pro Sekunde für ungefähr 85 Jahre, und eine Datei mit diesen vielen UUIDs mit 16 Bytes pro UUID würde ungefähr 45 Exabyte groß sein, ein Vielfaches größer als die größten derzeit existierenden Datenbanken die Größenordnung von Hunderten von Petabyte.

...

Damit eine Wahrscheinlichkeit von einer Milliarde Duplikaten besteht, müssen 103 Billionen UUIDs der Version 4 generiert werden.

sheki
quelle
56
Ich würde auch von dieser Seite zitieren: "Die Wahrscheinlichkeit eines Duplikats würde ungefähr 50% betragen, wenn jede Person auf der Erde 600 Millionen UUIDs besitzt."
Jeff Axelrod
24
Dies gilt nur für echte Zufälligkeit, nicht für Pseudozufallszahlen wie Javas-UUIDs.
Markus
9
@ Markus: völlig falsch. Die Wahrscheinlichkeit von Kollisionen für die besonders kryptografisch starken guten pseudozufälligen RNGs unterscheidet sich nicht von der "wahren" Zufälligkeit.
Michael Borgwardt
6
@ Eric - Ich denke, es liegt an Ihnen, Ihre Behauptung zu stützen. FWIW, die einzigen Szenarien, die ich mir vorstellen kann, in denen UUIDs vom Typ 4 häufiger kollidieren würden, als es die Wahrscheinlichkeitstheorie vorschreibt: 1) eine schlechte Quelle für Krypto-Zufallszahlen oder 2) eine UUID-Bibliothek, die kompromittiert wurde.
Stephen C
13
Dies beantwortet die gestellte Frage nicht. Die Frage betrifft die Qualität der Zufälligkeit in Java und UUID.randomUUID()nicht die theoretischen Chancen für einen bestimmten perfekten Zufallszahlengenerator.
Kratenko
69

Hat jemand Erfahrungen zu teilen?

Es gibt 2^122mögliche Werte für eine UUID vom Typ 4. (Die Spezifikation besagt, dass Sie 2 Bits für den Typ und weitere 4 Bits für eine Versionsnummer verlieren.)

Angenommen, Sie würden 1 Million zufällige UUIDs pro Sekunde generieren, wäre die Wahrscheinlichkeit, dass in Ihrem Leben ein Duplikat auftritt, verschwindend gering. Und um das Duplikat zu erkennen, müssten Sie das Problem lösen, 1 Million neue UUIDs pro Sekunde mit allen UUIDs zu vergleichen, die Sie zuvor generiert haben 1 !

Die Wahrscheinlichkeit, dass jemand im wirklichen Leben ein Duplikat erlebt hat (dh tatsächlich bemerkt hat ), ist noch geringer als verschwindend gering ... aufgrund der praktischen Schwierigkeit, nach Kollisionen zu suchen.

Jetzt verwenden Sie normalerweise einen Pseudozufallszahlengenerator, keine Quelle für wirklich zufällige Zahlen. Aber ich denke , wir können sicher sein , dass , wenn Sie einen anerkennenswerten Anbieter für Ihre Verschlüsselungsstärke Zufallszahl verwendet wird , dann ist es wird kryptographische Stärke sein, und die Wahrscheinlichkeit von Wiederholungen wird das gleiche wie für ein Ideal sein (nicht vorgespannt) Zufallszahlengenerator .

Wenn Sie jedoch eine JVM mit einem "kaputten" Krypto-Zufallszahlengenerator verwenden, sind alle Wetten ungültig. (Und das könnte einige der Problemumgehungen für Probleme mit "Entropiemangel" auf einigen Systemen beinhalten. Oder die Möglichkeit, dass jemand an Ihrer JRE herumgebastelt hat, entweder auf Ihrem System oder vorgelagert.)


1 - Angenommen, Sie haben "eine Art binären Baum" verwendet, wie von einem anonymen Kommentator vorgeschlagen, benötigt jede UUID O(NlogN)Bits des RAM-Speichers, um Nunterschiedliche UUIDs darzustellen, wobei eine geringe Dichte und zufällige Verteilung der Bits vorausgesetzt wird. Multiplizieren Sie dies nun mit 1.000.000 und der Anzahl der Sekunden, für die Sie das Experiment ausführen möchten. Ich denke nicht, dass dies für die Zeitspanne, die zum Testen auf Kollisionen eines hochwertigen RNG benötigt wird, praktisch ist. Nicht einmal mit (hypothetischen) klugen Darstellungen.

Stephen C.
quelle
4
"(Und um das Duplikat zu erkennen, müssten Sie das Problem lösen, 1 Million neue UUIDs pro Sekunde mit allen zuvor generierten UUIDs zu vergleichen!)" - Dieser Teil ist relativ einfach, vorausgesetzt, Sie haben Ihre UUids in einigen gespeichert Art von binärer Baumstruktur, es wäre nur ein Baumabstieg pro neuer UUID. Sie müssten es nicht einzeln mit allen zuvor generierten Benutzeroberflächen vergleichen.
user467257
20

Ich bin kein Experte, aber ich würde annehmen, dass sich im Laufe der Jahre genügend kluge Leute mit Javas Zufallszahlengenerator befasst haben. Daher würde ich auch annehmen, dass zufällige UUIDs gut sind. Sie sollten also wirklich die theoretische Kollisionswahrscheinlichkeit haben (die für alle möglichen UUIDs etwa 1: 3 × 10 ^ 38 beträgt . Weiß jemand, wie sich dies nur für zufällige UUIDs ändert? Ist es 1/(16*4)die oben genannte?)

Aus meiner praktischen Erfahrung habe ich bisher noch nie Kollisionen gesehen. Ich werde wahrscheinlich an dem Tag, an dem ich meinen ersten bekomme, einen erstaunlich langen Bart bekommen haben;)

sfussenegger
quelle
10
Aus Wikipedia: ... Mit anderen Worten, erst nachdem in den nächsten 100 Jahren pro Sekunde 1 Milliarde UUIDs generiert wurden, würde die Wahrscheinlichkeit, nur ein Duplikat zu erstellen, bei etwa 50% liegen.
MaVRoSCy
1
Eigentlich sagt Wikipedia, dass es für die nächsten 85 Jahre ist ... Ich sage, rechnen Sie nicht damit, irgendwo hat jemand die gleiche UUID wie Sie generiert
smac89
12

Bei einem ehemaligen Arbeitgeber hatten wir eine eindeutige Spalte, die eine zufällige UUID enthielt. Wir haben in der ersten Woche nach dem Einsatz eine Kollision bekommen. Sicher, die Chancen sind gering, aber sie sind nicht Null. Aus diesem Grund enthält Log4j 2 UuidUtil.getTimeBasedUuid. Es wird eine UUID generiert, die 8.925 Jahre lang eindeutig ist, solange Sie nicht mehr als 10.000 UUIDs / Millisekunde auf einem einzelnen Server generieren.

Besucher
quelle
2
Ja. Die Frage bezieht sich jedoch auf zufällige (dh Typ-4) UUIDs.
Stephen C
1
Es wird nach der Wahrscheinlichkeit einer Kollision gefragt. Die Implikation ist, dass er sicher sein will, sie zu vermeiden.
Besucher
1
(Die Kollision war höchstwahrscheinlich auf eine kaputte Zufallsquelle für die Aussaat der PRNGs zurückzuführen. Ich dachte, es war möglich, dass es sich um einen reinen Zufall handelte.)
Stephen C
9

Das ursprüngliche Generierungsschema für UUIDs bestand darin, die UUID-Version mit der MAC-Adresse des Computers zu verketten, der die UUID generiert, und mit der Anzahl der Intervalle von 100 Nanosekunden seit der Einführung des Gregorianischen Kalenders im Westen. Durch die Darstellung eines einzelnen Punktes im Raum (Computer) und der Zeit (Anzahl der Intervalle) ist die Wahrscheinlichkeit einer Kollision der Werte praktisch gleich Null.

Alex2Ustas
quelle
1
Diese Erklärung macht mich optimistisch, Kollisionen in der Praxis nicht zu sehen. Können Sie auf eine Referenz für diese Aussage verweisen (ein Quellcode wäre sogar noch besser)?
Dragan Marjanović
Gefunden dies in den Spezifikationen ietf.org/rfc/rfc4122.txt . Trotzdem wäre es toll, die Umsetzung zu sehen.
Dragan Marjanović
1
Dieses Schema implementiert Java jedoch nicht. Java implementiert eine UUID vom Typ 4, die rein zufällig ist und weder MAC-Adresse noch Zeit enthält. Da es mittlerweile viele physische und virtuelle Geräte gibt, auf denen Sie Ihre MAC-Adresse auswählen können, garantiert der ursprüngliche Algorithmus keine Eindeutigkeit.
Søren Boisen
8

In vielen Antworten wird erläutert, wie viele UUIDs generiert werden müssten, um eine 50% ige Kollisionswahrscheinlichkeit zu erreichen. Eine Kollisionswahrscheinlichkeit von 50%, 25% oder sogar 1% ist jedoch für eine Anwendung wertlos, bei der eine Kollision (praktisch) unmöglich sein muss.

Werden andere Ereignisse, die auftreten können und tatsächlich auftreten, von Programmierern routinemäßig als "unmöglich" abgetan?

Wenn wir Daten auf eine Festplatte oder einen Speicher schreiben und wieder zurücklesen, gehen wir davon aus, dass die Daten korrekt sind. Wir verlassen uns auf die Fehlerkorrektur des Geräts, um Beschädigungen zu erkennen. Die Wahrscheinlichkeit von unentdeckten Fehlern liegt jedoch tatsächlich bei 2 bis 50 .

Wäre es nicht sinnvoll, einen ähnlichen Standard auf zufällige UUIDs anzuwenden? Wenn Sie dies tun, werden Sie feststellen, dass eine "unmögliche" Kollision in einer Sammlung von rund 100 Milliarden zufälligen UUIDs möglich ist (2 36,5 ).

Dies ist eine astronomische Zahl, aber Anwendungen wie die Einzelabrechnung in einem nationalen Gesundheitssystem oder die Protokollierung von Hochfrequenzsensordaten auf einer großen Anzahl von Geräten könnten definitiv an diese Grenzen stoßen. Wenn Sie den nächsten Per Anhalter durch die Galaxis schreiben , versuchen Sie nicht, jedem Artikel UUIDs zuzuweisen!

erickson
quelle
Zum Vergleich: Die Chance, einen Powerball-Jackpot zu gewinnen, beträgt 1 zu 300 Millionen, aber ein Umsatz von 10 bis 20 Millionen Tickets ist typisch. Der Punkt ist, dass viele Menschen "unmöglich" als etwas weniger als eine Chance in Hunderten von Millionen definieren.
Erickson
4

Da sich die meisten Antworten auf die Theorie konzentrierten, denke ich, dass ich der Diskussion etwas hinzufügen kann, indem ich einen praktischen Test gebe, den ich gemacht habe. In meiner Datenbank habe ich ungefähr 4,5 Millionen UUIDs, die mit Java 8 UUID.randomUUID () generiert wurden. Die folgenden sind nur einige, die ich herausgefunden habe:

c0f55f62 -b990-47bc-8caa-f42313669948

c0f55f62 -e81e-4253-8299-00b4322829d5

c0f55f62 -4979-4e87-8cd9-1c556894e2bb


b9ea2498-fb32-40ef-91ef-0ba 00060fe64

be87a209-2114-45b3-9d5a-86d 00060fe64


4a8a74a6-e972-4069-b480-b dea1177b21f

12fb4958-bee2-4c89-8cf8-e dea1177b21f

Wenn es wirklich zufällig wäre, wäre die Wahrscheinlichkeit, solche ähnlichen UUIDs zu haben, erheblich gering (siehe Bearbeiten), da wir nur 4,5 Millionen Einträge berücksichtigen. Also, auch wenn diese Funktion gut ist, in Bezug auf die nicht mit Kollisionen, für mich scheint es nicht , dass gut , wie es in der Theorie wäre.

Bearbeiten :

Viele Leute scheinen diese Antwort nicht zu verstehen, deshalb werde ich meinen Standpunkt klarstellen: Ich weiß, dass die Ähnlichkeiten "klein" und weit von einer vollständigen Kollision entfernt sind. Ich wollte jedoch nur die UUID.randomUUID () von Java mit einem echten Zufallszahlengenerator vergleichen, was die eigentliche Frage ist.

In einem echten Zufallszahlengenerator würde die Wahrscheinlichkeit, dass der letzte Fall eintritt, bei = 0,007% liegen. Daher denke ich, dass meine Schlussfolgerung steht.

Die Formel wird in diesem Wiki-Artikel en.wikipedia.org/wiki/Birthday_problem erklärt

André Pinheiro
quelle
6
Das ist nicht wahr. Diese Art von Ähnlichkeiten würde selbst bei einem echten Zufallszahlengenerator auf 4,5-M-UUids auftreten. Die Ähnlichkeiten zwischen den von Ihnen angegebenen UUIDs sind gering und weit entfernt von einer vollständigen Kollision.
user3711864
Ich stimme Ihnen voll und ganz zu, dass die Ähnlichkeiten "klein" und weit von einer vollständigen Kollision entfernt sind. Ich wollte jedoch nur die UUID.randomUUID () von Java mit einem echten Zufallszahlengenerator vergleichen (dies ist die Frage). Mit einigen Berechnungen können wir sehen, dass in einem echten Zufallszahlengenerator die Wahrscheinlichkeit, dass der letzte Fall eintritt, bei 1-e ^ (- 4500000 ^ 2 / (2 * 36 ^ 11)) = 0,007% = 1 in a liegt 13k. Ich müsste sehr viel Glück haben :)
André Pinheiro
1
Wäre eine solche Teilkollision mit 4,5 Millionen Gegenständen und einer Chance von 1 zu 13.000 nicht 346 Mal zu erwarten ?
Ben Lee
Nein @BenLee, ich habe die Wahrscheinlichkeit berechnet, dass dieses Ereignis eintritt, wenn man bedenkt, dass wir 4,5 Millionen Artikel haben. Es ist keine 1 zu 13.000 Chance für jeden Gegenstand. Die Formel, die ich verwendet habe, finden Sie in diesem Wiki-Artikel en.wikipedia.org/wiki/Birthday_problem
André Pinheiro
2
Was war Ihre Erwartung? Ähnlich ist nicht dasselbe, nicht wahr?
Koray Tugay
3

Ich spiele letztes Jahr bei einer Lotterie und habe noch nie gewonnen ... aber es scheint, dass die Lotterie Gewinner hat ...

doc: http://tools.ietf.org/html/rfc4122

Typ 1: nicht implementiert. Kollisionen sind möglich, wenn die UUID im selben Moment generiert wird. impl kann künstlich a-synchronisiert werden, um dieses Problem zu umgehen.

Typ 2: Sehen Sie niemals eine Implementierung.

Typ 3: md5 Hash: Kollision möglich (128 Bit-2 technische Bytes)

Typ 4: zufällig: Kollision möglich (als Lotterie). Beachten Sie, dass das jdk6-Gerät keinen "wahren" sicheren Zufall verwendet, da der PRNG-Algorithmus nicht vom Entwickler ausgewählt wird und Sie das System zwingen können, ein "schlechtes" PRNG-Algo zu verwenden. Ihre UUID ist also vorhersehbar.

Typ 5: sha1 Hash: nicht implementiert: Kollision möglich (160 Bit-2 technische Bytes)

Giher
quelle
4
Die Wahrscheinlichkeit, im Lotto zu gewinnen, liegt vielleicht bei einer von 10 oder 100 Millionen (10 ^ 7 oder 10 ^ 8) oder so ähnlich. Die Wahrscheinlichkeit einer Kollision mit einer 128-Bit-Zufallszahl beträgt 3,4 * 10 ^ 28. Gib mir jederzeit einen Lottoschein!
Stephen C
0

Wir verwenden die zufällige UUID von Java seit mehr als einem Jahr in unserer Anwendung und das zu sehr. Aber wir stoßen nie auf eine Kollision.

Afsar
quelle