Quand dois-je utiliser l'uuid.uuid1 () vs. uuid.uuid4 () en python?

je comprends les différences entre les deux, de la docs.

uuid1() :

Générer un UUID à partir d'un ID hôte, d'un numéro de séquence et de l'heure courante

uuid4() :

Générer un UUID aléatoire.

So uuid1 utilise des informations machine/séquence/temps pour générer un UUID. Quels sont les avantages et les inconvénients de chacune?

je sais uuid1() peut avoir les préoccupations de la vie privée, car il est basé sur la machine de l'information. Je me demande s'il n'y a pas plus subtil en choisissant l'un ou l'autre. J'utilise juste uuid4() maintenant, puisque c'est un UUID complètement aléatoire. Mais je me demande si je devrais utiliser uuid1 pour réduire le risque de collisions.

en gros, je cherche les conseils des gens sur les meilleures pratiques d'utilisation de l'un par rapport à l'autre. Merci!

182
demandé sur guettli 2009-11-23 22:48:24

6 réponses

uuid1() est garanti pour ne pas produire de collisions (dans l'hypothèse où vous ne créez pas trop d'entre eux en même temps). Je ne l'utiliserais pas s'il est important qu'il n'y ait pas de connexion entre le uuid et l'ordinateur, car l'adresse mac est utilisée pour le rendre unique sur tous les ordinateurs.

vous pouvez créer des doublons en créant plus de 2 14 uuid1 en moins de 100ns, mais ce n'est pas un problème pour la plupart des cas d'utilisation.

uuid4() génère, comme vous l'avez dit, un UUID aléatoire. La probabilité d'une collision est vraiment, vraiment, vraiment petite. D'assez petite taille, que vous ne devriez pas vous inquiéter à ce sujet. Le problème, c'est qu'un mauvais générateur de nombres aléatoires rend plus susceptibles d'avoir des collisions.

Cette excellente réponse de Bob Aman , résume joliment. (Je recommande la lecture de l'ensemble de la réponse.)

franchement, dans un seul espace d'application sans acteurs malveillants, le l'extinction de toute vie sur terre se produisent bien avant que vous avez un collision, même sur une version 4 UUID, même si vous en générez pas mal. Uuid par seconde.

229
répondu Georg Schölly 2017-05-23 11:55:07

un cas où vous pouvez considérer uuid1() plutôt que uuid4() est lorsque les UUIDs sont produits sur des machines distinctes , par exemple lorsque plusieurs transactions en ligne sont traitées sur plusieurs machines à des fins de mise à l'échelle.

dans une telle situation, les risques d'avoir des collisions dues à de mauvais choix dans la façon dont les générateurs de nombres pseudo-aléatoires sont initialisés, par exemple, et aussi les nombres potentiellement plus élevés d'UUIDs produits rendre plus probable la possibilité de créer des Id en double.

un autre intérêt de uuid1() , dans ce cas est que la machine où chaque GUID a été initialement produit est implicitement enregistrée (dans la partie" node " de UUID). Ceci et les informations de temps, peuvent aider si seulement avec le débogage.

30
répondu mjv 2013-09-29 05:16:57

mon équipe vient de rencontrer des problèmes en utilisant UUID1 pour un script de mise à niveau de la base de données où nous avons généré ~120k UUIDs en quelques minutes. La collision UUID a entraîné la violation d'une contrainte principale.

nous avons mis à jour des centaines de serveurs mais sur nos instances EC2 Amazon nous avons rencontré ce problème à quelques reprises. Je pense que la mauvaise résolution de l'horloge et de passer à UUID4 résolu pour nous.

12
répondu Mattias Lagergren 2015-12-21 08:51:22

une chose à noter lors de l'utilisation de uuid1 , si vous utilisez l'appel par défaut (sans donner le paramètre clock_seq ) vous avez une chance de tomber dans des collisions: vous avez seulement 14 bits de hasard (générer 18 entrées dans les 100ns vous donne environ 1% de chance d'une collision voir paradoxe d'anniversaire/attaque). Le problème ne se produira jamais dans la plupart des cas d'utilisation, mais sur une machine virtuelle avec une mauvaise résolution d'horloge il vous mordra.

5
répondu Guillaume 2014-06-17 18:49:50

peut-être que quelque chose qui n'a pas été mentionné est celui de la localité.

une adresse MAC ou un ordre basé sur le temps (UUID1) peut se permettre une performance accrue de la base de données, car il est moins de travail pour trier les nombres plus étroitement-ensemble que ceux distribués au hasard (UUID4) (voir ici ).

un deuxième problème lié, est que L'utilisation D'UUID1 peut être utile pour le débogage, même si les données d'origine sont perdues ou pas explicitement stockées (ce qui est évidemment en conflit avec la question de la vie privée mentionnée par l'OP).

3
répondu c z 2017-04-13 16:46:30

en plus de la réponse acceptée, il y a une troisième option qui peut être utile dans certains cas:

v1 avec random MAC ("v1mc")

vous pouvez faire un hybride entre v1 et v4 en générant délibérément des UUIDs v1 avec une adresse MAC de diffusion aléatoire (ceci est autorisé par la spécification v1). La v1 UUID résultante est dépendante du temps (comme la v1 régulière), mais ne dispose pas de toutes les informations spécifiques à l'hôte (comme v4). Il est également beaucoup plus proche de v4 dans Il est résistance aux collisions: v1mc = 60 bits de temps + 61 bits aléatoires = 121 bits uniques; v4 = 122 bits aléatoires.

le premier endroit où je l'ai rencontré était la fonction uuid_generate_v1mc () de Postgres. J'ai depuis utilisé l'équivalent python suivant:

from os import urandom
from uuid import uuid1
_int_from_bytes = int.from_bytes  # py3 only

def uuid1mc():
    # NOTE: The constant here is required by the UUIDv1 spec...
    return uuid1(_int_from_bytes(urandom(6), "big") | 0x010000000000)

(note: j'ai une version plus longue + plus rapide qui crée l'objet UUID directement; peut poster Si quelqu'un veut)


dans le cas de grands volumes d'appels/seconde, cela a le potentiel d'échappement aléatoire du système. Vous pourrait utiliser le module stdlib random à la place (il sera probablement aussi plus rapide). Mais attention: il ne faut que quelques centaines d'UUIDs avant qu'un attaquant puisse déterminer l'état de RNG, et donc prédire partiellement les UUIDs futurs.

import random
from uuid import uuid1

def uuid1mc_insecure():
    return uuid1(random.getrandbits(48) | 0x010000000000)
0
répondu Eli Collins 2017-08-22 16:15:02