Quando devo usar uuid.uuid1 () vs. uuid.uuid4 () em python?

Entendo as diferenças entre os dois dos documentos.

uuid1():
Gerar um UUID a partir de um ID de máquina, número de sequência e a hora actual

uuid4():
Gerar um UUID Aleatório.

então uuid1 usa a informação máquina/sequência / tempo para gerar um UUID. Quais são os prós e contras de usar cada um?

Eu sei que pode ter preocupações de Privacidade, já que se baseia em informação de máquina. Será que há algo mais subtil ao escolher um ou restante. Eu só uso uuid4() Neste momento, uma vez que é um UUID completamente aleatório. Mas eu me pergunto se eu deveria estar usando {[[2]} para diminuir o risco de colisões.

Basicamente, estou à procura das dicas das pessoas para as melhores práticas de usar uma contra a outra. Obrigado!

 182
Author: guettli, 2009-11-23

6 answers

uuid1() é garantido não produzir quaisquer colisões (sob a suposição que você não criar muitos deles ao mesmo tempo). Eu não o usaria se fosse importante que não houvesse ligação entre o uuid e o computador, já que o endereço mac é usado para torná-lo único nos computadores.

Você pode criar duplicados criando mais de 214 uuid1 em menos de 100ns, mas isso não é um problema para a maioria dos casos de uso.

uuid4() gera, como você disse, um aleatório UUID. A chance de uma colisão é realmente, realmente, realmente pequena. Pequeno o suficiente para não te preocupares com isso. O problema é que um mau gerador de números aleatórios torna mais provável que tenha colisões.

Esta excelente resposta de Bob Aman resume tudo muito bem. (Eu recomendo ler toda a resposta.)

Francamente, num único espaço de Aplicação sem actores maliciosos, o a extinção de toda a vida na terra ocorrer muito antes de ter colisão, mesmo numa versão 4 UUID, mesmo que estejas a gerar alguns UUIDs por segundo.
 229
Author: Georg Schölly, 2017-05-23 11:55:07

Um exemplo, quando você pode considerar uuid1() em vez de uuid4() é quando os UUIDs são produzidos em máquinas separadas, por exemplo, quando várias transações on-line são de processo em várias máquinas para fins de dimensionamento.

Em tal situação, o risco de colisões devido a más escolhas na forma como os geradores de números pseudo-aleatórios são inicializados, por exemplo, e também os números potencialmente mais elevados de UUIDs produzidos tornam mais provável a possibilidade de criar identificações duplicadas.

Outro interesse de {[[0]}, nesse caso é que a máquina onde cada GUID foi inicialmente produzido é implicitamente gravada (na parte" nó " do UUID). Esta e a informação de tempo, pode ajudar, nem que seja apenas com depuração.

 30
Author: mjv, 2013-09-29 05:16:57
A minha equipa teve problemas ao usar o UUID1 para um programa de actualização da base de dados, onde gerámos ~120k UUIDs em poucos minutos. A colisão UUID levou à violação de uma restrição de chave primária. Nós atualizamos 100s de servidores, mas em nossas instâncias da Amazon EC2 encontramos este problema algumas vezes. Suspeito que a falta de resolução do relógio e a mudança para UUID4 resolveram-no para nós.
 12
Author: Mattias Lagergren, 2015-12-21 08:51:22

Uma coisa a ter em conta ao usar uuid1, se usar a chamada predefinida (sem indicar o parâmetro clock_seq), terá uma hipótese de se deparar com colisões: só tem 14 bits de aleatoriedade (gerando 18 entradas dentro de 100ns dá-lhe cerca de 1% de hipótese de colisão, veja o paradoxo/ataque do aniversário). O problema nunca vai ocorrer na maioria dos casos de uso, mas em uma máquina virtual com resolução de relógio ruim que vai morder você.

 5
Author: Guillaume, 2014-06-17 18:49:50
Talvez algo que não foi mencionado seja o local.

Um endereço MAC ou uma ordenação baseada no tempo (UUID1) pode dar-se ao luxo de aumentar o desempenho da base de dados, uma vez que é menos trabalho ordenar números mais próximos do que aqueles distribuídos aleatoriamente (UUID4) (ver aqui).

Uma segunda questão relacionada, é que o uso do UUID1 pode ser útil na depuração, mesmo que os dados de origem sejam perdidos ou não explicitamente armazenados (isto está obviamente em conflito com a questão de Privacidade mencionada pelo PO).

 3
Author: c z, 2017-04-13 16:46:30

Além da resposta aceite, há uma terceira opção que pode ser útil em alguns casos:

V1 com MAC aleatório ("v1mc")

Poderá criar um híbrido entre v1 & v4 gerando deliberadamente UUIDs v1 com um endereço MAC de difusão aleatória (isto é permitido pela spec v1). O UUID v1 resultante é dependente do tempo (como o V1 regular), mas carece de toda a informação específica da máquina (como o v4). Também está muito mais perto do v4 em sua resistência à colisão: v1mc = 60 bits de tempo + 61 bits aleatórios = 121 bits únicos; v4 = 122 bits aleatórios.

O primeiro lugar que encontrei foi a função Postgres' uuid_ generate_ v1mc(). Desde então, usei o seguinte equivalente python:

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)

(nota: eu tenho uma versão mais longa e mais rápida que cria o objeto UUID diretamente; pode postar se alguém quiser)


No caso de grandes volumes de chamadas/segundo, isso tem o potencial de aleatoriedade do sistema de escape. Você Pode usar o stdlib random módulo em vez disso (provavelmente também será mais rápido). Mas seja avisado: basta apenas algumas centenas de UUIDs antes que um atacante possa determinar o estado RNG, e, assim, prever parcialmente UUIDs futuros.

import random
from uuid import uuid1

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