web-dev-qa-db-fra.com

Quelle est la qualité de UUID.randomUUID de Java?

Je sais que les variables aléatoires ID ont une très très faible probabilité de collision en théorie, mais je me demande, en pratique, quelle est la qualité de Java randomUUID() en termes de non avoir une collision? Quelqu'un a-t-il une expérience à partager?

293
Alvin

UUID utilise Java.security.SecureRandom , qui est supposé être "fort sur le plan cryptographique". Bien que l'implémentation réelle ne soit pas spécifiée et puisse varier entre les machines virtuelles (ce qui signifie que toutes les déclarations concrètes ne sont valides que pour une machine virtuelle spécifique), elle exige toutefois que la sortie passe avec succès le test du générateur de nombres aléatoires statistiques.

Il est toujours possible pour une implémentation de contenir des bogues subtils qui gâchent tout cela (voir Bogue de génération de clé OpenSSH), mais je ne pense pas qu'il y ait de raison concrète de s'inquiéter du caractère aléatoire de Java UUID.

159
Michael Borgwardt

Wikipedia a une très bonne réponse http://en.wikipedia.org/wiki/Universally_unique_identifier#Collisions

le nombre d'UUID aléatoires de la version 4 à générer pour avoir une probabilité d'au moins une collision de 50% est de 2,71 quintillions, calculé comme suit:

...

Ce nombre équivaut à générer 1 milliard d’UUID par seconde pendant environ 85 ans. Un fichier contenant autant d’UUID, à 16 octets par UUID, serait d’environ 45 exaoctets, bien plus volumineux que les plus grandes bases de données existantes l'ordre de centaines de pétaoctets.

...

Ainsi, pour qu'il y ait une chance sur un milliard de duplication, 103 trillions d'UUID de version 4 doivent être générés.

111
sheki

Quelqu'un a-t-il une expérience à partager?

Il existe 2^122 valeurs possibles pour un UUID de type 4. (La spécification indique que vous perdez 2 bits pour le type et 4 autres bits pour un numéro de version.)

En supposant que vous produisiez 1 million d'UUID aléatoires par seconde, les chances qu'un doublon se produise au cours de votre vie seraient extrêmement réduites. Et pour détecter le doublon, vous devez résoudre le problème de la comparaison d’un million de nouveaux UUID par seconde avec tous les UUID que vous avez générés précédemment .1!

Les chances que quiconque ait expérimenté (c'est-à-dire réellement remarqué ) un duplicata dans la vie réelle soient encore plus faibles que minuscule ... en raison de la difficulté pratique de regarder pour les collisions.

Maintenant, bien sûr, vous utiliserez généralement un générateur de nombres pseudo-aléatoires, et non une source de nombres réellement aléatoires. Mais je pense que nous pouvons être certains que si vous utilisez un fournisseur fiable pour vos nombres aléatoires de force cryptographique, il sera une force cryptographique et sa probabilité de répétitions seront les mêmes que pour un générateur de nombres aléatoires idéal (non biaisé).

Cependant, si vous utilisiez une machine virtuelle avec un générateur de nombre crypto-aléatoire "défectueux", tous les paris sont désactivés. (Et cela pourrait inclure certaines des solutions de contournement pour les problèmes de "manque d'entropie" sur certains systèmes. Ou la possibilité que quelqu'un ait modifié votre JRE, sur votre système ou en amont.)


1 - En supposant que vous utilisiez "une sorte de binaire binaire" tel que proposé par un commentateur anonyme, chaque UUID aura besoin de O(NlogN) bits de la mémoire RAM pour représenter N UUID distincts en supposant une faible densité et une distribution aléatoire des bits. Maintenant, multipliez ce chiffre par 1 000 000 et le nombre de secondes pendant lequel vous allez exécuter l’expérience. Je ne pense pas que ce soit pratique compte tenu du temps nécessaire pour tester les collisions d'un GRN de haute qualité. Pas même avec des représentations intelligentes (hypothétiques).

67
Stephen C

Je ne suis pas un expert, mais je suppose que suffisamment de personnes intelligentes ont examiné le générateur de nombres aléatoires de Java au fil des ans. Par conséquent, je suppose également que les UUID aléatoires sont bons. Donc, vous devriez vraiment avoir la probabilité de collision théorique (qui est d'environ 1: × 10 ^ 38 pour tous les UUID possibles. Quelqu'un sait-il comment cela change pour les UUID aléatoires seulement? _ 1/(16*4) de ce qui précède?)

D'après mon expérience pratique, je n'ai jamais vu de collision jusqu'à présent. J'aurai probablement eu une barbe étonnamment longue le jour où j'aurai mon premier;)

20
sfussenegger

Le schéma de génération original pour les UUID consistait à concaténer la version de UUID avec l'adresse MAC de l'ordinateur générant l'UUID, ainsi que le nombre d'intervalles de 100 nanosecondes depuis l'adoption du calendrier grégorien en Occident. En représentant un seul point dans l'espace (l'ordinateur) et le temps (le nombre d'intervalles), le risque de collision de valeurs est en réalité nul.

9
Alex2Ustas

Chez un ancien employeur, nous avions une colonne unique contenant un uuid aléatoire. Nous avons eu une collision la première semaine après son déploiement. Bien sûr, les chances sont faibles mais elles ne sont pas nulles. C'est pourquoi Log4j 2 contient UuidUtil.getTimeBasedUuid. Il générera un UUID unique pendant 8 925 ans, à condition de ne pas générer plus de 10 000 UUID/milliseconde sur un seul serveur.

7
rgoers

Beaucoup de réponses discutent du nombre d'UUID qu'il faudrait générer pour atteindre une chance de collision de 50%. Mais une chance de collision de 50%, 25%, voire 1% ne vaut rien pour une application où la collision doit être (pratiquement) impossible.

Les programmeurs considèrent-ils systématiquement comme "impossibles" d’autres événements qui peuvent se produire et se produisent?

Lorsque nous écrivons des données sur un disque ou dans une mémoire et que nous les relisons, nous prenons pour acquis que les données sont correctes. Nous nous fions à la correction d'erreur de l'appareil pour détecter toute corruption. Mais le risque d'erreurs non détectées est en réalité d'environ 2-50.

Ne serait-il pas judicieux d'appliquer une norme similaire à des UUID aléatoires? Si vous le faites, vous constaterez qu'une collision "impossible" est possible dans une collection d'environ 100 milliards d'UUID aléatoires (236,5).

C'est un nombre astronomique, mais des applications telles que la facturation détaillée dans un système de santé national ou l'enregistrement de données de capteurs haute fréquence sur un large éventail d'appareils pourraient bien dépasser ces limites. Si vous écrivez le prochain Guide de l'auto-stoppeur sur le Galaxy, n'essayez pas d'attribuer des UUID à chaque article!

6
erickson

Je joue à la loterie l'année dernière et je n'ai jamais gagné .... mais il semble que la loterie ait des gagnants ...

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

Type 1: non implémenté. les collisions sont possibles si l'uuid est généré au même moment. impl peut être artificiellement synchronisé afin de contourner ce problème.

Type 2: ne jamais voir une implémentation.

Type 3: hash md5: collision possible (128 bits-2 octets techniques)

Type 4: aléatoire: collision possible (comme une loterie). notez que l'implémentation jdk6 n'utilise pas de "véritable" aléatoire sécurisé car l'algorithme PRNG n'est pas choisi par le développeur et vous pouvez forcer le système à utiliser un "mauvais" PRNG algo. Donc, votre UUID est prévisible.

Type 5: hash sha1: non implémenté: collision possible (160 octets techniques sur 2 bits)

3
Giher

Comme la plupart des réponses se sont concentrées sur la théorie, je pense pouvoir ajouter quelque chose à la discussion en faisant un test pratique que j'ai fait. Dans ma base de données, j'ai environ 4,5 millions d'UUID générés à l'aide de Java 8 UUID.randomUUID (). Voici quelques exemples que j'ai découverts:

c0f55f62 - b990-47bc-8caa-f42313669948

c0f55f62 - e81e-4253-8299-00b4322829d5

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


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

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


4a8a74a6-e972-4069-b480-b dea1177b21f

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

Si c'était vraiment aléatoire, la probabilité d'avoir ce type d'UUID similaire serait considérablement faible (voir edit), puisque nous n'envisageons que 4,5 millions d'entrées. Donc, bien que cette fonction soit bonne, en termes de non collision, pour moi cela ne semble pas cette bon comme ce serait en théorie.

Edit:

Beaucoup de gens semblent ne pas comprendre cette réponse, alors je vais clarifier mon propos: je sais que les similitudes sont "petites" et loin d'une collision totale. Cependant, je voulais juste comparer le UUID.randomUUID () de Java avec un véritable générateur de nombres aléatoires, qui est la vraie question.

Dans un vrai générateur de nombres aléatoires, la probabilité que le dernier cas se produise serait d'environ  = 0,007%. Par conséquent, je pense que ma conclusion est.

La formule est expliquée dans cet article de wiki en.wikipedia.org/wiki/Birthday_problem

2
André Pinheiro

Nous utilisons l’UUID aléatoire de Java dans notre application depuis plus d’un an et cela de manière très extensive. Mais nous ne rencontrons jamais de collision.

1
Afsar