Quand êtes-vous vraiment obligé d'utiliser UUID dans le cadre de la conception?

StackOverflow https://stackoverflow.com/questions/703035

  •  22-08-2019
  •  | 
  •  

Question

Je ne vois pas vraiment le point de UUID . Je sais que la probabilité d'une collision est effectivement nul , mais effectivement nul est pas près impossible.

Quelqu'un peut-il donner un exemple où vous avez pas d'autre choix que d'utiliser UUID? De toutes les utilisations que je l'ai vu, je peux voir une autre conception sans UUID. Bien sûr, la conception pourrait être un peu plus compliqué, mais au moins il n'a pas une probabilité non nulle de l'échec.

UUID sent comme des variables globales pour moi. Il existe de nombreuses façons variables globales rendent la conception plus simple, mais son design paresseux.

Était-ce utile?

La solution

J'ai écrit le générateur UUID / analyseur pour Ruby, donc je me considère comme raisonnablement bien informé sur le sujet. Il existe quatre grandes versions UUID:

Version 4 UUID sont essentiellement seulement 16 octets d'éléments aléatoires tiré d'un générateur de nombres aléatoires sécurisé, avec un certain bit tripotant pour identifier la version UUID et variante. Ceux-ci sont très peu susceptibles d'entrer en collision, mais il pourrait se produire si un PRNG est utilisé ou si vous venez tout juste d'avoir vraiment, vraiment, vraiment, vraiment, la chance vraiment mauvais.

versions 5 et 3 UUID utilisent le SHA1 et les fonctions de hachage MD5 respectivement, de combiner un espace de noms avec un morceau de données déjà uniques pour générer un UUID. Cela, par exemple, vous permettra de produire un UUID à partir d'une URL. Collisions ici ne sont possibles que si la fonction de hachage sous-jacente a également une collision.

Version 1 UUID sont les plus communs. Ils utilisent l'adresse MAC de la carte réseau (qui, à moins usurpée, doit être unique), ainsi qu'un horodatage, ainsi que l'habituel bit bidouilles pour générer l'UUID. Dans le cas d'une machine qui ne dispose pas d'une adresse MAC, les 6 octets de noeud sont générés par un générateur de nombres aléatoires cryptographiquement sûre. Si deux UUID sont générés dans l'ordre assez rapidement que l'horodatage correspond à l'UUID précédent, l'horodatage est incrémenté de 1. Collisions ne doit pas se produire à moins que l'un des événements suivants se produit: L'adresse MAC est usurpée; Une machine exécutant deux applications génératrices de UUID différentes produit UUID au même moment précis; Deux machines sans une carte réseau ou sans accès au niveau utilisateur à l'adresse MAC sont données la même séquence de noeud aléatoire, et générer des UUID au même moment précis; Nous manquons d'octets pour représenter l'horodatage et retournement à zéro.

De façon réaliste, aucun de ces événements se produisent par hasard dans l'espace d'ID d'une seule application. À moins que vous acceptez ID, disons, une échelle d'Internet à l'échelle ou avec un environnement non sécurisé où les individus malveillants pourraient être en mesure de faire quelque chose de mal dans le cas d'une collision d'identité, il est tout simplement pas quelque chose que vous devriez vous inquiéter. Il est essentiel de comprendre que si vous arrive de générer la même version 4 UUID comme moi, dans la plupart des cas, il n'a pas d'importance. J'ai produit l'ID dans un espace d'identité complètement différente de la vôtre. Mon application ne saura jamais à propos de la collision si la collision n'a pas d'importance. Franchement, dans un seul espace d'application sans acteurs malveillants, l'extinction de toute vie sur la terre se produira longtemps avant que vous ayez une collision, même sur une version 4 UUID, même si vous générez un bon nombre UUID par seconde.

En outre, 2 ^ 64 * 16 est de 256 exaoctets. Comme, vous devez stocker 256 exaoctets une valeur d'ID avant que vous ayez une chance de 50% d'une collision d'identité dans un espace unique d'application.

Autres conseils

La seule chose que vous achetez UUID qui est très difficile à faire est par ailleurs d'obtenir un identifiant unique sans avoir à consulter ou de coordonner avec une autorité centrale . Le problème général d'être en mesure d'obtenir une telle chose sans une sorte d'infrastructure gérée est le problème des UUID résoudre.

J'ai lu que selon le paradoxe d'anniversaire la possibilité d'une collision survenant UUID est de 50% une fois 2 ^ 64 UUID ont été générés. Maintenant 2 ^ 64 est un nombre assez grand, mais une probabilité de 50% de collision semble beaucoup trop risqué (combien UUID par exemple, besoin d'exister avant qu'il y ait une chance de 5% de collision - même cela semble trop grande d'une probabilité) .

Le problème de cette analyse est double:

  1. UUID ne sont pas tout à fait au hasard - il y a des composantes majeures de l'UUID qui sont le temps et / ou de localisation. Donc, pour avoir une chance réelle à une collision, les UUID qui entrent en collision besoin Tobe généré exactement au même temps de différents générateurs de UUID. Je dirais que si il y a une chance raisonnable que plusieurs de UUID peuvent être générés en même temps, il y a assez d'autres gunk (y compris les informations ou bits aléatoires emplacement) pour faire le likeyhood d'une collision entre cet ensemble très petit nombre de UUID presque impossible .

  2. à proprement parler, UUID ne doivent être uniques parmi l'ensemble des autres UUID qu'ils pourraient être comparés. Si vous générez un UUID à utiliser comme une clé de la base de données, peu importe si un autre dans un univers alternatif mal que le même UUID est utilisé pour identifier une interface COM. Tout comme ça va causer aucune confusion s'il y a quelqu'un (ou quelque chose) d'autre nommé "Michael Burr" sur Alpha-Centauri.

Tout a une chance non nulle de l'échec. Je me concentrerais sur beaucoup plus susceptibles de se produire des problèmes (à savoir presque tout ce que vous pouvez penser) que la collision de UUID

L'accent mis sur « raisonnablement » ou, comme vous le dites, « efficace »: assez bon est de savoir comment fonctionne le monde réel. La quantité de travail de calcul impliqué dans la couverture l'écart entre « pratiquement unique » et « vraiment unique » est énorme. L'unicité est une courbe de rendement décroissant. À un certain point sur cette courbe, il y a une ligne entre l'endroit où « assez unique » est encore abordable, et nous courbe très forte. Le coût de l'ajout de plus unique devient assez grand. Infini unique a un prix infini.

UUID / GUID est, relativement parlant, d'une manière informatiquement rapide et facile de générer un identifiant qui peut être raisonnablement supposé être universellement unique. Ceci est très important dans de nombreux systèmes qui ont besoin d'intégrer les données des systèmes non liées au préalable. Par exemple: si vous avez un système de gestion de contenu qui fonctionne sur deux plates-formes différentes, mais à un moment donné besoin d'importer le contenu d'un système à l'autre. Vous ne voulez pas d'ID de changer, de sorte que vos références entre les données du système A restent intactes, mais vous ne voulez pas de collisions avec les données créées dans le système B. Un UUID résout ce.

Il est jamais absolument nécessaire de créer un UUID. Il est toutefois commode d'avoir une norme où hors ligne les utilisateurs peuvent générer chacun une clé à quelque chose avec une très faible probabilité de collision.

Cela peut aider dans la résolution de la réplication de base de données, etc ...

Il serait facile pour en ligne aux utilisateurs de générer des clés uniques pour quelque chose sans les frais généraux ou possibilité de collision, mais ce n'est pas ce UUID sont pour.

Quoi qu'il en soit, un mot sur la probabilité de collision, tirée de Wikipedia:

  

Pour mettre ces chiffres en perspective, son risque annuel d'être frappé   par une météorite est estimée à une chance sur 17 milliards, soit l'équivalent   les chances de créer quelques dizaines de billions de UUID en un an et   ayant un double. En d'autres termes, seulement après avoir généré 1 milliard   UUID chaque seconde pour les 100 prochaines années, la probabilité de créer   juste un double serait d'environ 50%.

Il y a aussi une probabilité non nulle que chaque particule de votre corps tunnel simultanément à travers la chaise sur laquelle vous êtes assis et vous trouverez tout à coup vous assis sur le sol.

Craignez-vous que?

Un exemple classique est lorsque vous répliquez entre deux bases de données.

DB (A) insère un enregistrement avec int ID 10 et en même temps DB (B) crée un record avec ID 10. Ceci est une collision.

Avec UUID cela ne se produira car ils ne correspondent pas. (Presque certainement)

J'ai un système pour éviter UUID. Configurer un serveur quelque part et avoir de telle sorte que chaque fois qu'un morceau de logiciel veut un identifiant unique universel, ils communiquent avec le serveur et il remet un. Simple!

Sauf qu'il ya des problèmes pratiques réels avec cela, même si nous ignorons la méchanceté pure et simple. En particulier, ce serveur peut échouer ou devenir inaccessible d'une partie de l'Internet. Faire face à l'échec du serveur nécessite la réplication, et qui est très difficile pour obtenir le droit (voir la documentation sur l'algorithme Paxos pourquoi la recherche de consensus est maladroit) et est assez trop lent. De plus, si tous les serveurs sont inaccessibles à partir d'une partie particulière de la « nette, pas des clients connectés à ce sous-réseau sera en mesure de faire quoi que ce soit parce qu'ils seront tous en attente de nouveaux ID.

Alors ... utiliser un simple algorithme probabiliste pour les générer qui est peu probable à l'échec au cours de la durée de vie de la Terre, ou (fonds et) construire une infrastructure importante qui va être un déploiement PITA et ont des défaillances fréquentes. Je sais qui j'irais pour.

Si vous regardez juste les alternatives par exemple pour une simple application de base de données, d'avoir à interroger la base de données à chaque fois avant de créer un nouvel objet, vous allez bientôt trouver que l'utilisation UUID peut effectivement réduire la complexité de votre système. D'accord - si vous utilisez les touches int sont 32bit, qui stockera dans un quart de la UUID 128bit. Attribuées - algorithmes de génération UUID prennent plus de puissance de calcul que simplement incrémenter un numéro. Mais - qui se soucie? Les frais généraux de la gestion d'une « autorité » d'attribuer des numéros uniques autrement facilement que l'emporte par des ordres de grandeur, en fonction de votre espace unique d'identification prévu.

UUID == conception paresseuse

Je suis en désaccord au sujet de son cueillette de vos combats. Si un double UUID est statistiquement impossible et les mathématiques est prouvé alors pourquoi vous inquiéter? Passer du temps la conception autour de votre petit système de génération de N UUID est peu pratique, il y a toujours une douzaine d'autres façons dont vous pouvez améliorer votre système.

Je ne comprends pas tous les discours sur la probabilité de collision. Je ne me soucie pas de collision. Je me soucie de la performance bien.

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

  

UUID sont une catastrophe de performance pour les très grandes tables. (200K lignes est   pas "très grand".)

     

Votre # 3 est vraiment mauvais lorsque le charcter SET est UTF8 - CHAR (36)   occupe 108 octets!

     

UUID (GUID) sont très "au hasard". En les utilisant soit comme un UNIQUE ou   clé primaire sur de grandes tables est très inefficace. Ceci est dû   avoir à sauter autour de la table / index chaque fois que vous insérez une nouvelle UUID   ou SELECT par UUID. Lorsque la table / index est trop volumineux pour tenir dans le cache   (Voir innodb_buffer_pool_size, qui doit être plus petite que la RAM,   généralement 70%), l'UUID « suivant » ne peut pas être mis en mémoire cache, d'où un disque lent   frappé. Lorsque la table / index est 20 fois plus grand que le cache, seulement 1/20   (5%) de hits sont mises en cache - vous êtes d'E / S lié

.      

Alors, ne pas utiliser UUID à moins que ce soit

     

vous avez des tables « petits », ou vous avez vraiment besoin d'eux en raison de la génération   ids uniques de différents endroits (et n'ont pas compris une autre façon   pour le faire). Plus sur le sujet UUID: http://mysql.rjweb.org/doc.php/uuid (Il   comprend des fonctions de conversion entre UUID standards 36-char et   BINARY (16).)

     

Ayant à la fois un UNIQUE AUTO_INCREMENT et UNIQUE UUID dans le même   la table est un déchet.

     

Lorsqu'un INSERT se produit, toutes les clés primaires uniques / doivent être vérifiés   doublons. Soit clé unique est suffisante pour l'exigence de InnoDB   d'avoir une clé primaire. BINARY (16) (16 octets) est quelque peu encombrant (e   argument contre qui en fait le PK), mais pas si mal. le bouffant   compte lorsque vous avez des clés secondaires. InnoDB vire de bord silencieusement le PK   sur l'extrémité de chaque clé secondaire. La principale leçon est ici pour   réduire le nombre de clés secondaires, en particulier pour les très grandes   les tables. Pour comparision: INT UNSIGNED est de 4 octets avec la gamme de 0..4   milliard. BIGINT est de 8 octets.

A mon dernier emploi, nous obtenions des objets de tiers qui ont été identifiés de manière unique avec UUID. Je mets dans une UUID-> longue table de recherche entier et utilisé entier long comme mes clés primaires, car il était beaucoup plus rapide de cette façon.

En utilisant la version 1 algorithme, il semble qu'il est impossible de collision sous la contrainte que moins de 10 UUID par milliseconde sont générés à partir de la même adresse MAC

  

Conceptuellement, l'original (version 1)   système de génération pour les UUID était de   concaténer la version UUID avec le   adresse MAC de l'ordinateur qui est   générer l'UUID, et avec le   nombre d'intervalles de 100 nanosecondes   depuis l'adoption du grégorien   calendrier dans l'Ouest. Dans la pratique, la   algorithme réel est plus complexe.   Ce régime a été critiqué dans   qu'il ne soit pas suffisamment « opaque »;   il révèle à la fois l'identité du   ordinateur qui a généré l'UUID et   l'heure à laquelle il l'a fait.

Quelqu'un me corrigera si je mal interprété comment cela fonctionne:

Pour ceux qui disent que les UUID sont une mauvaise conception parce qu'ils peut (à un ridiculement faible probabilité) entrent en collision, alors que votre DB généré clés ne seront pas ... vous savez le risque d'erreur humaine provoquant une collision sur votre DB généré clés en raison d'un besoin de non forseen est loin FAR FAR plus élevé que le risque de collision UUID4. Nous savoir que si le db est recréée il va commencer à 1 ids encore une fois, et combien d'entre nous ont dû recréer une table quand nous étions sûrs que nous aurions besoin jamais à? Je mettrais mon argent sur des choses quand safeness UUID commence à aller mal avec inconnus-inconnus un jour.

En dehors des cas où vous devez utiliser quelqu'un d'API d'autre qui exige un UUID, bien sûr, il y a toujours une autre solution. Mais ces alternatives vont résoudre tous les problèmes UUID faire? Est-ce que vous finissez par l'ajout de couches de hacks, chacun pour résoudre un problème différent, quand on aurait pu résoudre tous à la fois?

Oui, il est théoriquement possible pour les UUID d'entrer en collision. Comme d'autres l'ont noté, il est ridiculement peu probable au point qu'il est tout simplement pas à considérer. Il est jamais arrivé à ce jour et très probablement jamais. Oubliez ça.

La façon la plus « évidente » pour éviter les collisions est de laisser un seul serveur de générer des identifiants uniques sur chaque insert, ce qui crée évidemment des problèmes graves de performance et ne résout pas le problème de génération hors du tout. Oops.

L'autre solution « évidente » est une autorité centrale qui remet des blocs de numéros uniques à l'avance, ce qui est essentiellement ce que UUID V1 fait en utilisant l'adresse MAC de la machine de production (via l'IEEE PIAP). Mais en double adresses MAC ne se produisent parce que chaque vis de l'autorité centrale vers le haut par la suite, dans la pratique c'est beaucoup plus probable qu'une collision UUID V4. Oops.

Le meilleur argument contre l'utilisation UUID est qu'ils sont « trop grand », mais un (beaucoup) plus petit système échoueront inévitablement à résoudre les problèmes les plus intéressants; La taille de UUID est un effet secondaire inhérent à leur utilité à résoudre ces problèmes très.

Il est possible que votre problème n'est pas assez grand besoin que UUID offrent, et dans ce cas, ne hésitez pas à utiliser autre chose. Mais si votre problème se développe de façon inattendue (et presque tous), vous finirez par passer plus tard - et vous lancer pour ne pas les utiliser en premier lieu. Pourquoi la conception de l'échec quand il est tout aussi facile à concevoir pour le succès à la place?

UUID incarnent toutes les mauvaises pratiques de codage associées à des variables globales, mais en pire, car ils sont des variables superglobales qui peuvent être réparties sur différents morceaux de kit.

a récemment atteint un tel problème avec le remplacement d'une imprimante avec un modèle de remplacement exact, et a constaté qu'aucun des logiciels client fonctionnerait.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top