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

Je ne vois pas vraiment l’intérêt de l’ UUID . Je sais que la probabilité d’une collision est effectivement nulle , mais en réalité , rien n’est presque impossible.

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

UUID sent comme des variables globales pour moi. Il existe de nombreuses façons pour les variables globales de simplifier la conception, mais leur conception simplement paresseuse.

J’ai écrit le générateur / parsingur UUID pour Ruby, donc je me considère raisonnablement bien informé sur le sujet. Il existe quatre versions principales d’UUID:

Les UUID de la version 4 ne représentent que 16 octets d’aléatoire tirés d’un générateur de nombres aléatoires sécurisé sur le plan cryptographique, avec quelques changements de bits pour identifier la version et la variante de l’UUID. Celles-ci sont très peu susceptibles d’entrer en collision, mais cela pourrait arriver si un PRNG est utilisé ou si vous avez vraiment, vraiment, vraiment, vraiment de la malchance.

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

Les UUID de la version 1 sont les plus courants. Ils utilisent l’adresse MAC de la carte réseau (qui, à moins d’être usurpée, devrait être unique), plus un horodatage, ainsi que le twidding habituel pour générer l’UUID. Dans le cas d’une machine ne possédant pas d’adresse MAC, les 6 octets de noeud sont générés avec un générateur de nombres aléatoires sécurisé sur le plan cryptographique. Si deux UUID sont générés en séquence suffisamment rapidement pour que l’horodatage corresponde à l’UUID précédent, l’horodatage est incrémenté de 1. Les collisions ne doivent pas avoir lieu si l’une des situations suivantes ne se produit pas: L’adresse MAC est falsifiée; Une machine exécutant deux applications différentes générant des UUID produit des UUID au même moment; Deux machines sans carte réseau ou sans access utilisateur à l’adresse MAC reçoivent la même séquence de nœuds aléatoires et génèrent des identificateurs UUID au même moment; Nous manquons d’octets pour représenter l’horodatage et le retour à zéro.

De manière réaliste, aucun de ces événements ne se produit par accident dans l’espace d’identification d’une seule application. Si vous n’acceptez pas les identifiants sur, par exemple, à l’échelle d’Internet ou dans un environnement non fiable où des personnes malveillantes peuvent faire quelque chose de mal en cas de collision d’ID, vous ne devez pas vous inquiéter. Il est essentiel de comprendre que si vous générez la même version 4 UUID que moi, dans la plupart des cas, cela n’a pas d’importance. J’ai généré l’identifiant dans un espace d’identification complètement différent de la vôtre. Mon application ne sera jamais au courant de la collision, donc la collision n’a pas d’importance. Franchement, dans un seul espace d’application sans acteurs malveillants, l’extinction de toute vie sur Terre se produira bien avant une collision, même sur un UUID version 4, même si vous générez quelques UUID par seconde.

En outre, 2 ^ 64 * 16 correspond à 256 exaoctets. Comme dans, vous devez stocker 256 exaoctets d’ID avant que vous n’ayez une chance de 50% d’une collision d’ID dans un seul espace d’application.

La chose que les UUID achètent est très difficile à faire autrement: obtenir un identifiant unique sans avoir à consulter ou à coordonner avec une autorité centrale . Le problème général de pouvoir obtenir une telle chose sans une infrastructure gérée est le problème que les UUID résolvent.

J’ai lu que, selon le paradoxe de l’anniversaire, le risque de collision UUID est de 50% une fois que 2 ^ 64 UUID ont été générés. Maintenant, 2 ^ 64 est un nombre assez important, mais une probabilité de collision de 50% semble beaucoup trop risquée (par exemple, combien d’UUID doivent exister avant qu’il y ait 5% de risque de collision – même si cela semble être une probabilité trop grande) .

Le problème avec cette parsing est double:

  1. Les UUID ne sont pas totalement aléatoires – il existe des composants majeurs de l’UUID basés sur l’heure et / ou l’emplacement. Pour avoir une chance réelle de collision, les UUID en collision doivent être générés exactement au même moment à partir de différents générateurs UUID. Je dirais que bien qu’il y ait une chance raisonnable que plusieurs UUID puissent être générés en même temps, il y a assez de gunk (y compris des informations de localisation ou des bits aléatoires) pour que la collision entre ce très petit ensemble d’UUID soit presque impossible .

  2. À proprement parler, les UUID ne doivent être uniques que parmi les autres UUID auxquels ils pourraient être comparés. Si vous générez un UUID à utiliser comme clé de firebase database, cela n’a pas d’importance si un autre UUID est utilisé pour identifier une interface COM. Tout comme il ne causera aucune confusion si quelqu’un d’autre (ou quelque chose d’autre) s’appelle “Michael Burr” sur Alpha-Centauri.

Tout a une chance d’échec non nulle. Je me concentrerais sur des problèmes beaucoup plus susceptibles de se produire (c.-à-d. Presque tout ce que vous pouvez penser) que la collision des UUID

L’accent est mis sur “raisonnablement” ou, comme vous le dites, “efficacement”: le monde réel fonctionne bien. La quantité de travail informatique nécessaire pour couvrir cet écart entre “pratiquement unique” et “vraiment unique” est énorme. L’unicité est une courbe avec des rendements décroissants. À un certain moment sur cette courbe, il y a une ligne entre où «assez unique» est encore abordable, et ensuite nous courbons TRÈS fortement. Le coût de l’ajout d’unicité devient assez important. L’unicité infinie a un coût infini.

UUID / GUID est, relativement parlant, un moyen rapide et facile à calculer pour générer un identifiant que l’on peut raisonnablement supposer être universellement unique. Ceci est très important dans de nombreux systèmes qui doivent intégrer des données provenant de systèmes non connectés auparavant. Par exemple: si vous avez un système de gestion de contenu qui s’exécute sur deux plates-formes différentes, mais à un moment donné, vous devez importer le contenu d’un système dans un autre. Vous ne voulez pas que les identifiants changent, vos références entre les données du système A restnt donc intactes, mais vous ne voulez pas de collision avec les données créées dans le système B. Un UUID résout ce problème.

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

Cela peut aider à la résolution de réplication de firebase database, etc.

Il serait facile pour les utilisateurs en ligne de générer des clés uniques pour quelque chose sans la surcharge ou la possibilité de collision, mais ce n’est pas ce que sont les UUID.

Quoi qu’il en soit, un mot sur la probabilité de collision, extrait de Wikipedia:

Pour mettre ces chiffres en perspective, le risque annuel d’être frappé par une météorite est estimé à une chance sur 17 milliards, soit l’équivalent des probabilités de créer quelques dizaines de milliards d’UUID au cours d’une année et d’avoir un duplicata. En d’autres termes, ce n’est qu’après avoir généré 1 milliard d’UUID par seconde pendant les 100 années suivantes que la probabilité de créer un seul duplicata serait d’environ 50%.

Il existe également une probabilité non nulle que chaque particule de votre corps traverse simultanément la chaise sur laquelle vous êtes assis et que vous vous retrouviez soudainement assis par terre.

Vous inquiétez-vous de cela?

Un exemple classique est la réplication 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 enregistrement avec dans ID 10. Ceci est une collision.

Avec les UUID, cela ne se produira pas car ils ne correspondront pas. (presque certainement)

Si vous examinez simplement les alternatives, par exemple pour une simple application de firebase database, pour devoir interroger la firebase database chaque fois avant de créer un nouvel object, vous constaterez rapidement que l’utilisation d’UUID peut réduire la complexité de votre système. Certes, si vous utilisez les touches int, le 32bit sera stocké dans un quart de l’UUID 128 bits. Certes – les algorithmes de génération d’UUID prennent plus de puissance de calcul que simplement incrémenter un nombre. Mais – qui s’en soucie? La surcharge de la gestion d’une “autorité” pour atsortingbuer des numéros uniques autrement l’emporte facilement sur des ordres de grandeur, en fonction de votre espace d’ID d’unicité.

J’ai un plan pour éviter les UUID. Installez un serveur quelque part et ayez-le de sorte que chaque fois qu’un logiciel souhaite un identifiant unique, il contacte ce serveur et celui-ci en sort un. Simple!

Sauf qu’il y a de réels problèmes pratiques avec ceci, même si nous ignorons la malveillance pure et simple. En particulier, ce serveur peut échouer ou devenir inaccessible depuis une partie d’Internet. La gestion des pannes de serveur nécessite une réplication, et c’est très difficile à faire (voir la documentation sur l’algorithme de Paxos pour savoir pourquoi la création d’un consensus est difficile) et elle est également assez lente. De plus, si tous les serveurs sont inaccessibles depuis une partie particulière du réseau, aucun des clients connectés à ce sous-réseau ne pourra faire quoi que ce soit, car ils attendront tous de nouveaux identifiants.

Donc … utilisez un algorithme probabiliste simple pour les générer qui ne risque pas de tomber en panne pendant la durée de vie de la Terre, ou (financez et construisez) une infrastructure majeure qui sera un déploiement PITA et qui aura de fréquentes pannes. Je sais lequel choisir.

Sur UUID == conception paresseuse

Je ne suis pas d’accord sur le choix de vos combats. Si un UUID en double est statistiquement impossible et que les calculs sont prouvés, alors pourquoi s’inquiéter? Passer du temps à concevoir votre petit système de génération N UUID n’est pas pratique, il y a toujours une douzaine d’autres façons d’améliorer votre système.

Je ne parle pas de la probabilité d’une collision. Je me fiche de la collision. Je me soucie de la performance si.

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

Les UUID sont un désastre de performance pour les très grandes tables. (200K lignes n’est pas “très grand”.)

Votre # 3 est vraiment mauvais lorsque le paramètre CHARCTER SET est utf8 – CHAR (36) occupe 108 octets!

Les UUID (GUID) sont très “aléatoires”. Leur utilisation comme clé UNIQUE ou PRIMARY sur de grandes tables est très inefficace. Cela est dû à la nécessité de contourner la table / index chaque fois que vous insérez un nouvel 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 petit que la RAM, généralement 70%), le prochain UUID peut ne pas être mis en cache, ce qui ralentit le disque. Lorsque la table / index est 20 fois plus grande que le cache, seulement 1 / 20e (5%) des hits sont mis en cache – vous êtes lié aux E / S.

Donc, n’utilisez pas les UUID sauf si

vous avez des “petites” tables, ou vous en avez vraiment besoin car vous générez des identifiants uniques à partir de différents endroits (et vous n’avez pas trouvé d’autre moyen de le faire). Plus d’informations sur les UUIDs: http://mysql.rjweb.org/doc.php/uuid (inclut des fonctions de conversion entre les UUIDs de 36 caractères standard et BINARY (16)).

Avoir à la fois un AUTO_INCREMENT UNIQUE et un UUID UNIQUE dans la même table est un gaspillage.

Lorsqu’une INSERT survient, toutes les clés uniques / primaires doivent être vérifiées pour détecter les doublons. Une clé unique est suffisante pour que InnoDB ait une clé primaire. BINARY (16) (16 octets) est un peu volumineux (un argument contre le fait d’en faire le PK), mais pas si mal. L’encombrement est important lorsque vous avez des clés secondaires. InnoDB assigne silencieusement le PK à la fin de chaque clé secondaire. La principale leçon ici est de minimiser le nombre de clés secondaires, en particulier pour les très grandes tables. Pour comparaison: INT UNSIGNED est de 4 octets avec une plage de 0,4 milliard. BIGINT est de 8 octets.

En utilisant l’algorithme de la version 1, il semble impossible de se heurter à la contrainte voulant que moins de 10 UUID par milliseconde soient générés à partir de la même adresse MAC

Conceptuellement, le schéma de génération original (version 1) des UUID consistait à concaténer la version UUID avec l’adresse MAC de l’ordinateur qui génère l’UUID et avec le nombre d’intervalles de 100 nanosecondes depuis l’adoption du calendrier grégorien dans l’Ouest . En pratique, l’algorithme actuel est plus compliqué. Ce système a été critiqué en ce qu’il n’est pas suffisamment «opaque»; il révèle à la fois l’identité de l’ordinateur qui a généré l’UUID et l’heure à laquelle il l’a fait.

Quelqu’un me corrige si j’ai mal interprété son fonctionnement

Pour ceux qui disent que les UUIDs sont mal conçus car ils pourraient (à une probabilité ridiculement faible) se heurter, alors que les clés générées par la firebase database ne … vous connaissez le risque d’erreur humaine provoquant une collision sur les clés générées par la firebase database. -pour que le besoin soit FAR FAR FAR plus élevé que le risque de collision UUID4. Nous soaps que si la firebase database est recréée, elle démarrera les identifiants à 1, et combien d’entre nous ont dû recréer une table alors que nous étions sûrs de ne jamais en avoir besoin? Je mettrais mon argent sur la sécurité de l’UUID quand les choses commencent à mal tourner avec des inconnus inconnus chaque jour.

Lors de mon dernier emploi, nous recevions des objects de tiers identifiés de manière unique avec UUID. J’ai mis une table de recherche UUID-> Entier long et utilisé un entier long comme clé primaire parce que c’était beaucoup plus rapide.

Mis à part les cas où vous devez utiliser l’API de quelqu’un d’autre qui requirejs un UUID, bien sûr, il y a toujours une autre solution. Mais ces alternatives vont-elles résoudre tous les problèmes rencontrés par les UUID? Voulez-vous finir par append plus de couches de hacks, chacun pour résoudre un problème différent, alors que vous auriez pu tous les résoudre en même temps?

Oui, les UUID peuvent théoriquement entrer en collision. Comme d’autres l’ont noté, il est ridiculement improbable au point que cela ne vaut tout simplement pas la peine d’être considéré. Ce n’est jamais arrivé à ce jour et probablement jamais. Oublie ça.

Le moyen le plus “évident” d’éviter les collisions consiste à laisser un seul serveur générer des identifiants uniques sur chaque insertion, ce qui crée évidemment de sérieux problèmes de performances et ne résout pas du tout le problème de génération hors ligne. Oops.

L’autre solution «évidente» est une autorité centrale qui délivre des blocs de numéros uniques à l’avance, ce qui est essentiellement ce que fait UUID V1 en utilisant l’adresse MAC de la machine générasortingce (via l’IEEE OUI). Mais les adresses MAC dupliquées se produisent parce que chaque autorité centrale finit par se visser, de sorte qu’en pratique, cela est beaucoup plus probable qu’une collision UUID V4. Oops.

Le meilleur argument contre l’utilisation des UUID est qu’ils sont «trop gros», mais qu’un système (nettement) plus petit ne permettra pas de résoudre les problèmes les plus intéressants; La taille des UUID est un effet secondaire inhérent à leur utilité pour résoudre ces problèmes mêmes.

Il est possible que votre problème ne soit pas suffisamment grave pour nécessiter ce que les UUID offrent, et dans ce cas, n’hésitez pas à utiliser autre chose. Mais si votre problème se développe de manière inattendue (et la plupart le font), vous finirez par changer plus tard – et vous vous précipitez pour ne pas les utiliser en premier lieu. Pourquoi concevoir pour échec quand il est tout aussi facile de concevoir pour réussir?

Les UUID intègrent toutes les mauvaises pratiques de codage associées aux variables globales, mais elles sont encore plus mauvaises, car ce sont des variables globales qui peuvent être réparties sur différents éléments du kit.

Récemment rencontré un tel problème avec le remplacement d’une imprimante avec un modèle de remplacement exact, et a constaté qu’aucun des logiciels clients ne fonctionnerait.