Le nom et l'espace de noms peuvent être utilisés pour créer une hiérarchie d'UUID uniques (très probablement).
En gros, un UUID de type 3 ou de type 5 est généré en hachant ensemble un identifiant d'espace de noms avec un nom. Les UUID de type 3 utilisent MD5 et les UUID de type 5 utilisent SHA1. Seuls 128 bits sont disponibles et 5 bits sont utilisés pour spécifier le type, donc tous les bits de hachage ne sont pas inclus dans l'UUID. (MD5 est également considéré comme cryptographiquement cassé, et SHA1 est sur ses dernières jambes, alors ne l'utilisez pas pour vérifier les données qui doivent être "très sécurisées"). Cela dit, cela vous donne un moyen de créer une fonction de "hachage" répétable / vérifiable mappant un nom éventuellement hiérarchique sur une valeur probabiliste unique de 128 bits, agissant potentiellement comme un hachage hiérarchique ou MAC.
Supposons que vous ayez un magasin (clé, valeur), mais qu'il ne prend en charge qu'un seul espace de noms. Vous pouvez générer un grand nombre d'espaces de noms logiques distincts à l'aide des UUID de type 3 ou 5. Commencez par créer un UUID racine pour chaque espace de noms. Cela peut être un UUID de type 1 (hôte + horodatage) ou de type 4 (aléatoire) tant que vous le rangez quelque part. Vous pouvez également créer un UUID aléatoire pour votre racine (ou utiliser l' null
UUID: en 00000000-0000-0000-0000-000000000000
tant que racine), puis créer un UUID reproductible pour chaque espace de noms en utilisant " uuid -v5 $ROOTUUID $NAMESPACENAME
". Vous pouvez maintenant créer des UUID uniques pour les clés dans un espace de noms en utilisant "uuid -v5 $NAMESPACEUUID $KEY
". Ces UUID peuvent être jetés dans un seul magasin clé-valeur avec une forte probabilité d'éviter les collisions. Ce processus peut être répété de manière récursive, de sorte que si, par exemple, la" valeur "associée à une clé UUID représente à son tour une sorte d'espace de nom logique" "comme un bucket, un conteneur ou un répertoire, son UUID peut être utilisé à son tour pour générer des UUID plus hiérarchiques.
L'UUID de type 3 ou de type 5 généré contient un hachage (partiel) de l'ID de l'espace de noms et du nom dans l'espace de noms (clé). Il ne contient pas plus l'UUID de l'espace de noms qu'un message MAC ne contient le contenu du message à partir duquel il est encodé. Le nom est une chaîne "arbitraire" (octet) du point de vue de l'algorithme uuid. Sa signification dépend cependant de votre application. Il peut s'agir d'un nom de fichier dans un répertoire logique, d'un identifiant d'objet dans un magasin d'objets, etc.
Bien que cela fonctionne bien pour un nombre modérément grand d'espaces de noms et de clés, cela finit par s'essouffler si vous visez un très grand nombre de clés uniques avec une probabilité très élevée. L'entrée Wikipedia pour le problème d'anniversaire (aka Birthday Paradox) comprend un tableau qui donne les probabilités d'au moins une collision pour différents nombres de clés et tailles de table. Pour 128 bits, le hachage de 26 milliards de clés de cette manière a une probabilité de collision de p=10^-18
(négligeable), mais 26 trillions de clés, augmente la probabilité d'au moins une collision à p=10^-12
(un sur un trillion), et le hachage de 26*10^15
clés, augmente la probabilité de au moins une collision avecp=10^-6
(un sur un million). En ajustant pour 5 bits qui encodent le type UUID, il s'épuisera un peu plus vite, donc un billion de clés ont environ 1 chance sur un billion d'avoir une seule collision.
Voir http://en.wikipedia.org/wiki/Birthday_problem#Probability_table pour la table de probabilité.
Voir http://www.ietf.org/rfc/rfc4122.txt pour plus de détails sur les encodages UUID.
Les UUID de type 3 et de type 5 ne sont qu'une technique de remplissage d'un hachage dans un UUID.
Un hachage SHA1 produit 160 bits (20 octets); le résultat du hachage est converti en UUID.
Avec le hachage de 20 octets de SHA1:
(Notez que les deux premiers bits de «9» sont déjà 1 et 0, respectivement, donc cela n'a aucun effet).
Que dois-je hacher?
Vous vous demandez probablement ce que je suis censé hacher. En gros, vous hachez la concaténation de:
Vous préfixez votre chaîne avec un soi-disant espace de noms pour éviter les conflits de noms.
La RFC UUID prédéfinit quatre espaces de noms pour vous:
NameSpace_DNS
: {6ba7b810-9dad-11d1-80b4-00c04fd430c8}NameSpace_URL
: {6ba7b811-9dad-11d1-80b4-00c04fd430c8}NameSpace_OID
: {6ba7b812-9dad-11d1-80b4-00c04fd430c8}NameSpace_X500
: {6ba7b814-9dad-11d1-80b4-00c04fd430c8}Donc, vous pouvez hacher ensemble:
La RFC définit ensuite comment:
L'essentiel de base est de ne prendre que les 128 premiers bits, de placer un
5
dans l' enregistrement de type , puis de définir les deux premiers bits de laclock_seq_hi_and_reserved
section sur 1 et 0, respectivement.Plus d'exemples
Maintenant que vous avez une fonction qui génère un soi-disant Nom , vous pouvez avoir la fonction (en pseudo-code):
(Notez que l'endian-ness de votre système peut affecter les indices des octets ci-dessus)
Vous pouvez avoir des appels:
Revenons maintenant à votre question
L' espace de noms correspond à l'UUID que vous souhaitez. Cela peut être l'un des prédéfinis, ou vous pouvez créer le vôtre, par exemple:
Le nom est juste le texte que vous souhaitez ajouter à l'espace de noms, puis haché et inséré dans un UUID:
la source
Namespace_RectalForeignExtractedObject
je le ferais.Un nom n'est rien de plus qu'un identifiant unique dans un espace de noms. Le problème est que les espaces de noms sont souvent assez petits et que les noms dans l'un entrent souvent en conflit avec les noms d'autres. Par exemple, le numéro de plaque d'immatriculation (nom) de ma voiture est unique dans l'espace de noms de mon état DMV, mais il n'est probablement pas unique au monde; d'autres DMV d'état peuvent avoir utilisé le même nom dans leurs propres espaces de noms. Heck, quelqu'un d'autre peut avoir un numéro de téléphone (nom) qui correspond également parce que c'est encore un autre espace de noms, etc.
Les UUID peuvent être considérés comme habitant un seul espace de noms si vaste qu'il peut fournir un nom unique pour tout ; c'est ce que signifie «l'universel». Mais comment mappez-vous les noms existants dans d'autres espaces de noms à un UUID?
Une solution évidente consiste à générer un UUID (V1 ou V4) pour chaque élément afin de remplacer les anciens noms dans leurs espaces de noms disjoints. L'inconvénient est qu'ils sont beaucoup plus gros, vous devez communiquer tous les nouveaux noms à tous ceux qui ont une copie de votre ensemble de données, mettre à jour toutes vos API, etc. Il y a de fortes chances que vous ne puissiez pas vous débarrasser complètement des anciens noms Quoi qu'il en soit, ce qui signifie que maintenant chaque élément a deux noms, alors avez-vous amélioré ou pire les choses?
C'est là que V3 / V5 entre en jeu. Les UUID semblent tout aussi aléatoires que V4 mais sont en fait déterministes; toute personne ayant le bon UUID pour un espace de noms peut ensuite générer indépendamment le même UUID pour tout nom donné dans cet espace de noms. Vous n'avez pas du tout besoin de les publier ni même de les pré-générer puisque n'importe qui peut les créer à la volée au besoin!
Les noms DNS et les URL sont des espaces de noms très couramment utilisés, donc des UUID standard ont été publiés pour ceux-ci; Les OID ASN.1 et les noms X.500 ne sont pas aussi courants, mais les organismes de normalisation les adorent, ils ont donc publié des UUID d'espaces de noms standard pour eux aussi.
Pour tous les autres espaces de noms, vous devez générer votre propre UUID d'espace de noms (V1 ou V4) et le communiquer à toute personne qui en a besoin. Si vous avez plusieurs espaces de noms, il n'est clairement pas idéal de publier l'UUID pour chacun d'eux.
C'est là que la hiérarchie entre en jeu: vous créez un UUID "de base" (de n'importe quel type), puis vous l'utilisez comme espace de noms pour nommer vos autres espaces de noms! De cette façon, vous n'avez qu'à publier l'UUID de base (ou en utiliser un évident), et tout le monde peut calculer le reste.
Par exemple, restons nous voulions créer des UUID pour StackOverflow; qui a un nom évident dans l'espace de noms DNS, donc la base est évidente:
StackOverflow lui-même a des espaces de noms séparés pour les utilisateurs, les questions, les réponses, les commentaires, etc., mais ceux-ci sont également assez évidents:
Cette question particulière est # 10867405, donc son UUID serait:
Notez qu'il n'y a rien d' aléatoire dans ce processus, donc quiconque suit la même logique obtiendra la même réponse, mais l'espace de noms UUID est si vaste qu'il (effectivement, étant donné la sécurité d'un hachage cryptographique de 122 bits) ne heurtera jamais un UUID généré à partir de toute autre paire d'espace de nom / nom.
la source