Eu realmente não vejo o objetivo do UUID . Eu sei que a probabilidade de uma colisão é efetivamente nula , mas efetivamente nula não é nem perto do impossível.
Alguém pode dar um exemplo em que você não tem escolha a não ser usar o UUID? De todos os usos que já vi, posso ver um design alternativo sem o UUID. Certamente, o design pode ser um pouco mais complicado, mas pelo menos não tem uma probabilidade de falha diferente de zero.
UUID cheira a variáveis globais para mim. Existem várias maneiras pelas quais as variáveis globais criam um design mais simples, mas é apenas um design preguiçoso.
architecture
uuid
Pyrolistical
fonte
fonte
Respostas:
Eu escrevi o gerador / analisador de UUID para Ruby, por isso considero-me razoavelmente bem informado sobre o assunto. Existem quatro versões principais de UUID:
Os UUIDs da versão 4 são essencialmente apenas 16 bytes de aleatoriedade extraídos de um gerador de números aleatórios criptograficamente seguro, com algumas correções de bits para identificar a versão e a variante do UUID. É extremamente improvável que colidam, mas isso pode acontecer se um PRNG for usado ou se você tiver realmente, realmente, muito, muito, muito azar.
Os UUIDs das versões 5 e 3 usam as funções de hash SHA1 e MD5, respectivamente, para combinar um espaço para nome com uma parte dos dados já exclusivos para gerar um UUID. Isso permitirá, por exemplo, que você produza um UUID a partir de uma URL. As colisões aqui só são possíveis se a função hash subjacente também tiver uma colisão.
Os UUIDs da versão 1 são os mais comuns. Eles usam o endereço MAC da placa de rede (que, a menos que seja falsificado, deve ser exclusivo), além de um carimbo de data / hora, além da variação de bits usual para gerar o UUID. No caso de uma máquina que não possui um endereço MAC, os bytes de 6 nós são gerados com um gerador de números aleatórios criptograficamente seguro. Se dois UUIDs forem gerados em sequência com rapidez suficiente para que o registro de data e hora corresponda ao UUID anterior, o registro de data e hora será incrementado em 1. Colisões não devem ocorrer a menos que ocorra uma das seguintes situações: O endereço MAC é falsificado; Uma máquina executando dois aplicativos geradores de UUID diferentes produz UUIDs no mesmo momento; Duas máquinas sem uma placa de rede ou sem acesso no nível de usuário ao endereço MAC recebem a mesma sequência aleatória de nós e geram UUIDs no exato momento;
Realisticamente, nenhum desses eventos ocorre acidentalmente no espaço de ID de um único aplicativo. A menos que você aceite IDs em, por exemplo, uma escala na Internet ou com um ambiente não confiável em que indivíduos mal-intencionados possam fazer algo ruim no caso de uma colisão de IDs, isso não é algo com que você deva se preocupar. É fundamental entender que, se você gerar a mesma versão 4 UUID que eu, na maioria dos casos, isso não importa. Eu criei o ID em um espaço de ID completamente diferente do seu. Meu aplicativo nunca saberá sobre a colisão, portanto a colisão não importa. Francamente, em um único espaço de aplicativo sem atores maliciosos, a extinção de toda a vida na Terra ocorrerá muito antes de você ter uma colisão, mesmo em um UUID da versão 4, mesmo que você '
Além disso, 2 ^ 64 * 16 são 256 exabytes. Assim, você precisaria armazenar 256 exabytes de IDs antes de ter 50% de chance de uma colisão de IDs em um único espaço de aplicativo.
fonte
uuid.raw
fornecerá a sequência de bytes. Ohash
método não é útil para você. É usado para tabelas de hash e operações de comparação internamente no Ruby. Todos os métodos para converter de e para várias representações UUID são definidos como métodos de classe e devem ser prefixados com"parse"
.O que os UUIDs compram para você que é muito difícil de fazer é obter um identificador exclusivo sem precisar consultar ou coordenar uma autoridade central . O problema geral de conseguir algo assim sem algum tipo de infraestrutura gerenciada é o problema que os UUIDs resolvem.
Eu li que, de acordo com o paradoxo do aniversário, a chance de uma colisão de UUID ocorrer é de 50% depois que 2 ^ 64 UUIDs são gerados. Agora 2 ^ 64 é um número bastante grande, mas 50% de chance de colisão parece muito arriscada (por exemplo, quantos UUIDs precisam existir antes que haja 5% de chance de colisão - mesmo que pareça uma probabilidade muito grande) .
O problema com essa análise é duplo:
Os UUIDs não são totalmente aleatórios - existem componentes principais do UUID que são baseados no tempo e / ou no local. Portanto, para ter uma chance real de uma colisão, os UUIDs em colisão precisam ser gerados ao mesmo tempo a partir de diferentes geradores de UUID. Eu diria que, embora exista uma chance razoável de que vários UUIDs possam ser gerados ao mesmo tempo, há outras informações suficientes (incluindo informações de localização ou bits aleatórios) para tornar quase impossível a colisão entre esse conjunto muito pequeno de UUIDs. .
estritamente falando, os UUIDs só precisam ser exclusivos entre o conjunto de outros UUIDs com os quais podem ser comparados. Se você estiver gerando um UUID para usar como chave de banco de dados, não importa se em algum outro lugar em um universo alternativo maligno o mesmo UUID está sendo usado para identificar uma interface COM. Assim como não causará confusão se houver alguém (ou algo) chamado "Michael Burr" em Alpha-Centauri.
fonte
Tudo tem uma chance diferente de zero de falha. Eu me concentraria em problemas muito mais prováveis de ocorrer (ou seja, quase tudo o que você possa imaginar) do que a colisão de UUIDs
fonte
Uma ênfase em "razoavelmente" ou, como você diz, "efetivamente": bom o suficiente é como o mundo real funciona. A quantidade de trabalho computacional envolvido na cobertura dessa lacuna entre "praticamente único" e "verdadeiramente único" é enorme. Exclusividade é uma curva com retornos decrescentes. Em algum momento dessa curva, há uma linha entre onde "o suficiente" ainda é acessível e, em seguida, fazemos uma curva muito acentuada. O custo de adicionar mais exclusividade se torna bastante grande. Exclusividade infinita tem custo infinito.
UUID / GUID é, relativamente falando, uma maneira computacionalmente rápida e fácil de gerar um ID que pode ser razoavelmente considerado universalmente único. Isso é muito importante em muitos sistemas que precisam integrar dados de sistemas anteriormente desconectados. Por exemplo: se você possui um Sistema de Gerenciamento de Conteúdo que é executado em duas plataformas diferentes, mas em algum momento precisa importar o conteúdo de um sistema para outro. Você não deseja que os IDs sejam alterados, portanto suas referências entre os dados do sistema A permanecem intactas, mas não deseja colisões com os dados criados no sistema B. Um UUID resolve isso.
fonte
Nunca é absolutamente necessário criar um UUID. No entanto, é conveniente ter um padrão em que os usuários offline possam 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 os usuários online gerar chaves exclusivas para algo sem sobrecarga ou possibilidade de colisão, mas não é para isso que servem os UUIDs.
De qualquer forma, uma palavra sobre a probabilidade de colisão, retirada da Wikipedia:
fonte
Um exemplo clássico é quando você está replicando entre dois bancos de dados.
O DB (A) insere um registro com o ID int 10 e, ao mesmo tempo, o DB (B) cria um registro no ID 10. Isso é uma colisão.
Com os UUIDs, isso não acontece, pois eles não coincidem. (quase certamente)
fonte
Também existe uma probabilidade diferente de zero de que todas as partículas do seu corpo esculpam simultaneamente a cadeira em que você está sentado e de repente você se encontrará sentado no chão.
Você se preocupa com isso?
fonte
Eu tenho um esquema para evitar UUIDs. Configure um servidor em algum lugar e faça com que, toda vez que algum software deseje um identificador universal único, eles entrem em contato com esse servidor e ele o entregue. Simples!
Exceto que existem alguns problemas práticos reais com isso, mesmo que ignoremos a malícia total. Em particular, esse servidor pode falhar ou tornar-se inacessível em parte da Internet. Lidar com falhas do servidor requer replicação, e isso é muito difícil de acertar (consulte a literatura sobre o algoritmo Paxos para saber por que a construção de consenso é incômoda) e também é muito lenta. Além disso, se todos os servidores estiverem inacessíveis a partir de uma parte específica da rede, nenhum dos clientes conectados a essa sub-rede poderá fazer qualquer coisa, porque todos estarão aguardando novos IDs.
Então ... use um algoritmo probabilístico simples para gerá-los com probabilidade de falhar durante a vida útil da Terra ou (financiar e) construir uma infraestrutura importante que será uma PITA de implantação e tenha falhas frequentes. Eu sei qual eu escolheria.
fonte
Não recebo toda a conversa sobre a probabilidade de colisão. Eu não ligo para colisão. Eu me preocupo com o desempenho.
https://dba.stackexchange.com/a/119129/33649
fonte
Se você apenas olhar as alternativas, por exemplo, para um aplicativo de banco de dados simples, para consultar o banco de dados toda vez antes de criar um novo objeto, em breve descobrirá que o uso do UUID pode efetivamente reduzir a complexidade do seu sistema. Concedido - se você usar as chaves int, elas são de 32 bits, que serão armazenadas em um quarto do UUID de 128 bits. Concedido - os algoritmos de geração de UUID ocupam mais poder computacional do que simplesmente incrementar um número. Mas quem se importa? A sobrecarga de gerenciar uma "autoridade" para atribuir números únicos de outra maneira supera facilmente essa ordem de magnitude, dependendo do espaço de ID de exclusividade pretendido.
fonte
No UUID == design lento
Eu discordo é sobre escolher suas lutas. Se um UUID duplicado é estatisticamente impossível e a matemática é comprovada, por que se preocupar? Gastar tempo projetando em torno do seu pequeno sistema de geração de N UUID é impraticável; sempre há uma dúzia de outras maneiras de melhorar seu sistema.
fonte
No meu último trabalho, estávamos recebendo objetos de terceiros identificados exclusivamente com o UUID. Coloquei uma tabela de pesquisa de número inteiro longo UUID-> e usei o número inteiro longo como minhas chaves primárias, porque era muito mais rápido assim.
fonte
Usando o algoritmo da versão 1, parece impossível colisão sob a restrição de que menos de 10 UUIDs por milissegundo são gerados a partir do mesmo endereço MAC
Alguém me corrija se eu interpretar mal como funciona
fonte
Para aqueles que dizem que os UUIDs são de design ruim porque podem (com uma probabilidade ridiculamente pequena) colidir, enquanto as chaves geradas pelo DB não ... você sabe a chance de um erro humano causar uma colisão nas chaves geradas pelo DB por causa de algumas A necessidade prevista é MUITO MUITO MAIS alta do que a chance de colisão com o UUID4. Nós sabemos 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 certeza de que nunca iria precisar? Eu colocaria meu dinheiro na segurança do UUID quando as coisas começam a dar errado com o desconhecido-desconhecido a qualquer dia.
fonte
Além dos casos em que você precisa usar a API de outra pessoa que exige um UUID, é claro que sempre há outra solução. Mas essas alternativas resolverão todos os problemas que os UUIDs fazem? Você acabará adicionando mais camadas de hacks, cada uma para resolver um problema diferente, quando você poderia ter resolvido todas elas de uma vez?
Sim, é teoricamente possível que os UUIDs colidam. Como outros observaram, é ridiculamente improvável que não valha a pena considerar. Isso nunca aconteceu até agora e provavelmente nunca acontecerá. Esqueça isso.
A maneira mais "óbvia" de evitar colisões é permitir que um único servidor gere IDs únicos em cada inserção, o que obviamente cria sérios problemas de desempenho e não resolve o problema de geração offline. Opa
A outra solução "óbvia" é uma autoridade central que distribui blocos de números exclusivos com antecedência, que é essencialmente o que o UUID V1 faz usando o endereço MAC da máquina geradora (via IEEE OUI). Mas endereços MAC duplicados acontecem porque todas as autoridades centrais estragam eventualmente; portanto, 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 "grandes demais", mas um esquema (significativamente) menor inevitavelmente falhará na solução dos problemas mais interessantes; O tamanho dos UUIDs é um efeito colateral inerente à sua utilidade na solução desses mesmos problemas.
É possível que seu problema não seja grande o suficiente para precisar do que os UUIDs oferecem e, nesse caso, fique à vontade para usar outra coisa. Mas se o seu problema aumentar inesperadamente (e a maioria ocorre), você acabará mudando mais tarde - e se arrependerá por não usá-lo. Por que projetar para o fracasso quando é tão fácil projetar para o sucesso?
fonte
Os UUIDs incorporam todas as práticas ruins de codificação associadas a variáveis globais, apenas pior, pois são variáveis superglobais que podem ser distribuídas por diferentes peças do kit.
Recentemente, ocorreu um problema com a substituição de uma impressora por um modelo de substituição exato e constatou que nenhum software cliente funcionaria.
fonte