Eu entendo as diferenças entre os dois dos documentos.
uuid1()
:
Gerar um UUID a partir de um ID do host, número de sequência e hora atual
uuid4()
:
Gera um UUID aleatório.
Então uuid1
usa máquina / seqüência / info tempo para gerar um UUID. Quais são os prós e os contras de usar cada um?
Sei que uuid1()
pode ter preocupações com a privacidade, pois é baseado em informações da máquina. Gostaria de saber se há mais sutil ao escolher um ou outro. Eu apenas uso uuid4()
agora, já que é um UUID completamente aleatório. Mas me pergunto se devo usá-lo uuid1
para diminuir o risco de colisões.
Basicamente, estou procurando dicas das pessoas sobre práticas recomendadas sobre como usar uma vs. a outra. Obrigado!
Respostas:
uuid1()
é garantido que não produzirá colisões (sob a suposição de que você não crie muitas delas ao mesmo tempo). Eu não o usaria se fosse importante que não houvesse conexão entreuuid
o computador e o computador, pois o endereço mac é usado para torná-lo único nos computadores.Você pode criar duplicatas criando mais de 2 14 uuid1 em menos de 100ns, mas isso não é um problema para a maioria dos casos de uso.
uuid4()
gera, como você disse, um UUID aleatório. A chance de uma colisão é muito, muito, muito pequena. Pequeno o suficiente para não se preocupar com isso. O problema é que um gerador ruim de números aleatórios aumenta a probabilidade de colisões.Esta excelente resposta de Bob Aman resume bem. (Eu recomendo a leitura da resposta completa.)
fonte
uuid1
não produzirá necessariamente UUIDs exclusivos se você produzir vários por segundo no mesmo nó. Exemplo:[uuid.uuid1() for i in range(2)]
. A menos, claro, que algo estranho esteja acontecendo que eu esteja sentindo falta.uuid1
tem um número de sequência (quarto elemento no seu exemplo), então, a menos que você use todos os bits do contador, não terá colisão.Um exemplo, quando você pode considerar
uuid1()
em vez deuuid4()
é quando UUIDs são produzidos em máquinas separadas , por exemplo, quando várias transações on-line são processo em várias máquinas para fins de escala.Em tal situação, os riscos 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 o número potencialmente mais alto de UUIDs produzidos tornam mais provável a possibilidade de criação de IDs duplicados.
Outro interesse de
uuid1()
, nesse caso, é que a máquina onde cada GUID foi produzido inicialmente seja implicitamente registrada (na parte "nó" do UUID). Esta e as informações de tempo podem ajudar, mesmo que apenas com depuração.fonte
Minha equipe teve problemas ao usar o UUID1 para um script de atualização de banco de dados, onde geramos ~ 120k UUIDs em alguns minutos. A colisão de UUID levou à violação de uma restrição de chave primária.
Atualizamos centenas de servidores, mas em nossas instâncias do Amazon EC2 encontramos esse problema algumas vezes. Eu suspeito que a resolução do relógio é ruim e a mudança para o UUID4 resolveu isso para nós.
fonte
Uma coisa a ser observada ao usar
uuid1
, se você usar a chamada padrão (sem fornecer oclock_seq
parâmetro), terá chance de colidir: você tem apenas 14 bits de aleatoriedade (gerar 18 entradas dentro de 100ns oferece aproximadamente 1% de chance de colisão) paradoxo / ataque de aniversário). O problema nunca ocorrerá na maioria dos casos de uso, mas em uma máquina virtual com baixa resolução de relógio, ele o morderá.fonte
clock_seq
....Talvez algo que não tenha sido mencionado seja o da localidade.
Um endereço MAC ou um pedido com base no tempo (UUID1) pode proporcionar um desempenho aprimorado do banco de dados, pois é menos trabalhoso classificar números mais próximos do que os distribuídos aleatoriamente (UUID4) (veja aqui ).
Um segundo problema relacionado é que o uso do UUID1 pode ser útil na depuração, mesmo que os dados de origem sejam perdidos ou não sejam armazenados explicitamente (isso obviamente está em conflito com o problema de privacidade mencionado pelo OP).
fonte
Além da resposta aceita, há uma terceira opção que pode ser útil em alguns casos:
v1 com MAC aleatório ("v1mc")
Você pode fazer um híbrido entre v1 e v4 gerando deliberadamente UUIDs v1 com um endereço MAC de transmissão aleatória (isso é permitido pela especificação v1). O UUID da v1 resultante depende do tempo (como a v1 normal), mas não possui todas as informações específicas do host (como a v4). Também está muito mais próximo da 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 uuid_generate_v1mc () do Postgres . Desde então, usei o seguinte equivalente em python:
(nota: eu tenho uma versão mais longa + rápida que cria o objeto UUID diretamente; pode postar se alguém quiser)
No caso de grandes volumes de chamadas / segundo, isso pode esgotar a aleatoriedade do sistema. Você pode usar o
random
módulo stdlib (provavelmente também será mais rápido). Mas lembre-se: são necessárias apenas algumas centenas de UUIDs antes que um invasor possa determinar o estado do RNG e, portanto, prever parcialmente UUIDs futuros.fonte