Pergunta

Eu realmente não vejo o ponto de UUID . Eu sei que a probabilidade de uma colisão é efetivamente nulo , mas efetivamente nulo não está nem perto de impossível.

Alguém pode dar um exemplo onde você não tem escolha a não ser usar UUID? De todos os usos que eu vi, eu posso ver um projeto alternativo sem UUID. Claro que o design pode ser um pouco mais complicado, mas pelo menos ele não tem um diferente de zero probabilidade de falha.

UUID cheira como variáveis ??globais para mim. Há muitas maneiras variáveis ??globais fazem para design mais simples, mas o seu design apenas preguiçoso.

Foi útil?

Solução

Eu escrevi o UUID / gerador de analisador para Ruby, então eu me considero razoavelmente bem informado sobre o assunto. Há quatro versões principais UUID:

Versão 4 UUIDs são essencialmente apenas 16 bytes de aleatoriedade puxados a partir de um gerador de criptograficamente seguro número aleatório, com alguns bits girando para identificar a versão UUID e variante. Estes são extremamente improvável que colidem, mas poderia acontecer se um PRNG é usado ou se você só acontecerá a ter realmente, realmente, realmente, realmente, realmente má sorte.

Versão 5 e Versão 3 UUIDs usar o SHA1 e funções hash MD5 respectivamente, para combinar um namespace com um pedaço de dados já únicas para gerar um UUID. Isto, por exemplo, permitem que você produzir um UUID a partir de uma URL. Colisões aqui só são possíveis se a função hash subjacente também tem uma colisão.

Versão 1 UUIDs são os mais comuns. Eles usam o endereço da placa de rede MAC (que, a menos falsificado, deve ser único), além de um timestamp, além da habitual bit-twiddling para gerar o UUID. No caso de uma máquina que não tem um endereço MAC, os 6 bytes de nó são gerados com um gerador de números aleatórios criptograficamente segura. Se dois UUID são geradas em sequência rápida o suficiente para que o timestamp corresponde o UUID anterior, a hora é incrementado de 1. As colisões não deve ocorrer a menos que uma das acontece o seguinte: o endereço MAC é falsificado; Uma máquina que executa duas aplicações geradoras UUID diferentes produz UUID no mesmo momento; Duas máquinas sem um cartão ou rede sem acesso nível de utilizador para o endereço MAC é dada a mesma sequência aleatória nó, e gerar UUID no mesmo momento; Nós corremos para fora de bytes para representar o timestamp e sobreposição de volta para zero.

Na realidade, nenhum desses eventos ocorrem por acidente dentro do espaço ID de um único aplicativo. A menos que você está aceitando IDs, digamos, uma escala de toda a Internet, ou com um ambiente não confiável onde os indivíduos mal-intencionados podem ser capaz de fazer algo ruim, no caso de uma colisão ID, não é apenas algo que você deve se preocupar. É fundamental entender que se você acontecer para gerar a mesma versão 4 UUID como eu, na maioria dos casos, não importa. Eu já gerou o ID em um espaço ID completamente diferente da sua. Meu aplicativo nunca vai saber sobre a colisão de modo a colisão não importa. Francamente, em um espaço de aplicação única, sem atores maliciosos, a extinção de toda a vida na Terra irá ocorrer muito antes de você ter uma colisão, mesmo em uma versão 4 UUID, mesmo se você está gerando algumas UUIDs por segundo.

Além disso, 2 ^ 64 * 16 é de 256 exabytes. Como em, você precisaria para armazenar 256 exabytes valor de IDs antes que você teve uma chance de 50% de uma colisão ID em um único espaço de aplicação.

Outras dicas

A única coisa que UUIDs comprar-lhe que é muito difícil fazer o contrário é obter um identificador único sem ter que consultar ou coordenar com uma autoridade central . O problema geral de ser capaz de conseguir tal coisa sem algum tipo de infra-estrutura gerida é o problema os UUIDs resolver.

Eu li que de acordo com o paradoxo do aniversário a chance de uma colisão que ocorre UUID é de 50% uma vez a 2 ^ 64 UUIDs foram gerados. Agora 2 ^ 64 é um número muito grande, mas 50% de chance de colisão parece muito arriscado (por exemplo, quantas UUIDs precisa existir antes que haja uma chance de 5% de colisão - mesmo que parece ser muito grande de uma probabilidade) .

O problema com que a análise é dupla:

  1. UUIDs não são totalmente aleatória - existem grandes componentes do UUID que são tempo e / ou baseados em localização. Portanto, para ter alguma chance real em uma colisão, os UUIDs colidem precisa tobe gerado no momento exato o mesmo tempo de diferentes geradores UUID. Eu diria que, enquanto há uma chance razoável de que vários UUID do pode ser gerado ao mesmo tempo, não há o suficiente outro lamaçal (incluindo informações de localização ou bits aleatórios) para fazer a likeyhood de uma colisão entre este conjunto muito pequeno de UUIDs quase impossíveis .

  2. estritamente falando, UUIDs só precisa ser exclusivo entre o conjunto de outros UUIDs que eles possam ser comparados contra. Se você está gerando um UUID para usar como uma chave de banco de dados, não importa se em outro lugar em um universo alternativo mal que o mesmo UUID está sendo usado para identificar uma interface COM. Assim como ele vai causar nenhuma confusão se há alguém (ou algo) else com o nome "Michael Burr" na Alpha-Centauri.

Tudo tem uma chance diferente de zero de falha. Gostaria de concentrar-se em muito mais provável de ocorrer problemas (ou seja, quase qualquer coisa que você pode pensar) do que a colisão de UUIDs

Uma ênfase na "razoavelmente" ou, como você diz, "efetivamente": bom o suficiente é como funciona o mundo real. A quantidade de trabalho computacional envolvido na cobertura de essa lacuna entre "praticamente único" e "verdadeiramente única" é enorme. Exclusividade é uma curva com rendimentos decrescentes. Em algum ponto nessa curva, há uma linha entre onde "o suficiente única" ainda é acessível, e então nós curva muito acentuada. O custo de adicionar mais singularidade torna-se muito grande. singularidade infinita tem custo infinito.

UUID / GUID é, relativamente falando, uma forma computacionalmente rápida e fácil de gerar um ID que pode ser razoavelmente assumido ser universalmente único. Isto é muito importante em muitos sistemas que precisam integrar dados de sistemas previamente desconectados. Por exemplo: se você tem um sistema de gerenciamento de conteúdo que é executado em duas plataformas diferentes, mas em algum ponto necessidade de importar o conteúdo de um sistema para o outro. Você não quer IDs para a mudança, para que seus referências entre os dados do sistema Uma permanecem intactos, mas você não quer nenhum colisões com dados criados no sistema B. A UUID resolve isso.

Nunca é absolutamente necessário para criar um UUID. É, no entanto conveniente ter um padrão onde desligada os usuários podem cada gerar uma chave para algo com uma probabilidade muito baixa de colisão.

Isso pode ajudar na resolução de replicação de banco de dados etc ...

Seria fácil para on-line aos usuários gerar chaves exclusivas para algo sem a sobrecarga ou possibilidade de colisão, mas não é isso que UUIDs são para.

De qualquer forma, uma palavra sobre a probabilidade de colisão, tirado de Wikipedia:

Para colocar estes números em perspectiva, o risco anual de um de ser atingido por um meteorito é estimada para ser uma chance em 17 bilhões, o equivalente para as chances de criação de algumas dezenas de trilhões de UUIDs em um ano e Tendo um duplicado. Em outras palavras, somente depois de gerar 1 bilhão UUIDs cada segundo para os próximos 100 anos, a probabilidade de criar apenas uma duplicata seria cerca de 50%.

Há também uma probabilidade não nula de que cada partícula em seu corpo irá simultaneamente túnel através da cadeira que você está sentado e de repente você vai encontrar-se sentada no chão.

Você se preocupa com isso?

Um exemplo clássico é quando você está replicando entre dois bancos de dados.

DB (A) insere um registro com ID int 10 e, ao mesmo tempo DB (B) cria um um registro com a ID 10. Esta é uma colisão.

Com UUIDs isso não vai acontecer, pois não irá corresponder. (Quase certamente)

Eu tenho um esquema para evitar UUIDs. Configurar um servidor em algum lugar e tê-lo de modo que cada vez que algum pedaço de software quer um identificador exclusivo universal, eles entrar em contato com esse servidor e entrega um para fora. Simples!

Só que existem alguns problemas práticos reais com isso, mesmo se ignorarmos malícia definitivas. Em particular, esse servidor pode falhar ou se tornar inacessível a partir de parte da internet. Lidar com a falha do servidor requer a replicação, e que de muito difícil para obter direito (ver a literatura sobre o algoritmo Paxos para o porquê construção de consenso é estranho) e é bastante lento também. Além disso, se todos os servidores são inacessíveis a partir de uma determinada parte do 'net, nenhum dos clientes conectados a essa sub-rede será capaz de fazer qualquer coisa, porque todos eles vão estar à espera de novas identificações.

Então ... utilizar um algoritmo probabilístico simples para gerá-los de que é improvável a falhar durante a vida da Terra, ou (fundo e) construir uma grande infra-estrutura que vai ser uma implantação PITA e têm falhas frequentes. Eu sei qual eu iria para.

Se você só olhar para as alternativas, por exemplo, para uma aplicação de banco de dados simples, ter que consultar o banco de dados de cada vez antes de criar um novo objeto, você vai logo descobrir que usando UUID pode efetivamente reduzir a complexidade de seu sistema. Concedido - se você usar chaves int o são de 32 bits, que irá armazenar em um quarto do UUID de 128 bits. Concedido - algoritmos de geração UUID ocupam mais poder computacional do que simplesmente incrementar um número. Mas quem se importa? A sobrecarga de gerenciamento de uma "autoridade" para atribuir números de outra forma únicas facilmente supera a por ordens de magnitude, dependendo do seu espaço ID singularidade pretendido.

projeto preguiçoso Em UUID ==

Eu discordo sua sobre escolher suas lutas. Se um UUID duplicado é estatisticamente impossível e a matemática é comprovada, em seguida, por que se preocupar? Passar o tempo projetar em torno de seu sistema de geração de pequeno N UUID é impraticável, há sempre uma dúzia de outras maneiras que você pode melhorar seu sistema.

i não recebem toda a conversa sobre a probabilidade de colisão. Eu não me importo sobre colisão. Eu me importo com o desempenho embora.

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

UUIDs são um desastre desempenho para tabelas muito grandes. (200K linhas é não "muito grande".)

O nº 3 é muito ruim quando o charcter SET é utf8 - CHAR (36) ocupa 108 bytes!

UUIDs (GUIDs) são muito "aleatório". Usá-los tanto como um UNIQUE ou um chave primária em tabelas grandes é muito ineficiente. Isto é devido ter que saltar em torno da mesa / index cada vez que você inserir um novo UUID ou SELECT por UUID. Quando a tabela / índice é muito grande para caber no cache (Veja innodb_buffer_pool_size, que deve ser menor do que a RAM, tipicamente 70%), o 'próximo' UUID não podem ser armazenados em cache, portanto, um disco lento acertar. Quando a tabela / índice é 20 vezes tão grande quanto o cache, apenas 1/20 (5%) de acessos são armazenados em cache -. Você é I /-bound O

Assim, não use UUIDs a menos que qualquer

você tem "pequenas" tabelas, ou você realmente precisa deles por causa da geração ids únicos de diferentes lugares (e ainda não descobri uma outra maneira para fazê-lo). Mais sobre UUIDs: http://mysql.rjweb.org/doc.php/uuid (It inclui funções para a conversão entre 36 e UUID char-padrão BINARY (16).)

Tendo tanto um UNIQUE AUTO_INCREMENT e uma UUID UNIQUE no mesmo mesa é um desperdício.

Quando um INSERT ocorre, todas as chaves únicas / primários devem ser verificados para duplicatas. De qualquer chave única é suficiente para a exigência do InnoDB de ter uma chave primária. BINÁRIO (16) (16 bytes) é um pouco volumoso (a argumento contra tornando-o o PK), mas não tão ruim assim. o bulkiness importa quando você tem as chaves secundárias. InnoDB silenciosamente tachas o PK sobre a extremidade de cada chave secundária. A principal lição aqui é minimizar o número de chaves secundárias, especialmente para muito grande mesas. Para comparação: unsigned int é de 4 bytes com intervalo de 0..4 bilhão. BIGINT é de 8 bytes.

No meu último emprego, que iríamos conseguir objetos de terceiros que foram exclusivamente identificados com UUID. Eu coloquei em um UUID-> tabela de pesquisa inteiro longo e usado inteiro longo como minhas chaves primárias porque era muito mais rápido dessa forma.

Usando o algoritmo versão 1 parece que é colisão impossível sob a restrição de que menos de 10 UUIDs por milissegundo são gerados a partir do mesmo endereço MAC

Conceitualmente, o original (versão 1) esquema de geração para UUID era concatenar a versão UUID com o endereço MAC do computador que é gerando o UUID, e com o número de intervalos de 100 nanossegundos desde a adopção da Gregoriana calendário no Ocidente. Na prática, o algoritmo real é mais complicado. Este regime foi criticado em que não é suficientemente 'opaco'; que revela a identidade do computador que gerou o UUID e o momento em que o fez.

Alguém me corrija se eu mal interpretado como funciona

Para aqueles que dizem que os UUIDs são ruins projeto porque poderia (em algum probabilidade ridiculamente pequeno) colidem, enquanto o seu DB gerado chaves não vai ... você sabe a chance de erro humano causando um colisão em seu db gerado chaves por causa de alguma necessidade un-forseen é muito longe longe maior do que a chance de UUID4 colisão. Nós sei que se o db é recriado ele vai começar ids em 1 de novo, e como muitos de nós tiveram que recriar uma mesa quando estávamos certo de que nunca precisa? Eu colocaria meu dinheiro em UUID safeness quando o material começa a ir mal com desconhecidos-incógnitas qualquer dia.

Além de casos onde você tem que API uso de outra pessoa que exige um UUID, é claro que há sempre uma outra solução. Mas será que essas alternativas resolver todas os problemas que UUIDs fazer? Você vai acabar adicionando mais camadas de hacks, cada um para resolver um problema diferente, quando você poderia ter resolvido todos eles de uma vez?

Sim, é teoricamente possível para UUIDs a colidir. Como outros já mencionado, é ridiculamente improvável a tal ponto que não é apenas a pena considerar. Isso nunca aconteceu até agora e provavelmente nunca será. Esquecê-la.

A maneira mais "óbvio" para evitar colisões é permitir que um único servidor gerar identificações exclusivas sobre cada inserção, o que obviamente cria sérios problemas de desempenho e não resolve o problema geração desligada em tudo. Opa.

A outra solução "óbvia" é uma autoridade central que distribui blocos de números exclusivos de antecedência, o que é essencialmente o que UUID V1 faz usando o endereço MAC da máquina geradora (através do IEEE OUI). Mas duplicar endereços MAC acontecem porque todos os parafusos da autoridade central até, eventualmente, por isso, na prática, isso é muito mais provável do que uma colisão UUID V4. Opa.

O melhor argumento contra o uso de UUIDs é que eles são "muito grande", mas um (significativamente) menor do esquema fracassará inevitavelmente para resolver a maioria dos problemas interessantes; tamanho UUIDs é um efeito colateral inerente de sua utilidade em resolver esses mesmos problemas.

É possível que seu problema não é grande o suficiente para necessidade que UUIDs oferecer, e, nesse caso, não hesite em usar outra coisa. Mas se o seu problema cresce inesperadamente (e a maioria faz), você vai acabar mudar mais tarde - e chutar a si mesmo por não usá-los em primeiro lugar. Por projeto para a falha quando é tão fácil de projetar para o sucesso em vez disso?

UUIDs incorporam toda a codificação de práticas associadas a variáveis ??globais, só que pior, pois são variáveis ??superglobais que podem ser distribuídos em diferentes peças de kit ruim.

Recentemente atingiu tal um problema com a substituição de uma impressora com um modelo substituto exato, e descobriu que nenhum dos software cliente iria funcionar.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top