Versões de UUID e quando usá-las
(ntietz.com)- UUIDs têm 8 versões, da v1 à v8; um número maior não significa que seja mais nova ou melhor, mas sim que diferentes métodos de geração estão definidos na RFC 9562
- As escolhas mais comuns se reduzem a v4 e v7: v4 é o padrão para IDs aleatórios, enquanto v7 é adequada quando é preciso ordenação pela hora de geração
- v1 e v6 usam os mesmos componentes, mas a v6 reorganiza a ordem dos campos para que, ao ordenar, o resultado siga a ordem de geração
- v3 e v5 criam UUIDs aplicando hash aos dados de entrada; v3 usa MD5, v5 usa SHA-1, e DNS e URL podem ser candidatos a valores de entrada
- Na prática, o fluxo mais útil é usar v7 em vez de v1/v6 quando possível; se for necessário um UUID baseado em dados de entrada, usar v5; e, se for necessário um UUID totalmente personalizado, avaliar v8
Como cada versão de UUID é gerada
- As versões de UUID vão da v1 à v8 e todas são definidas na RFC 9562
-
UUIDs baseados em tempo
- UUID Version 1 é gerado com timestamp, contador monotônico e endereço MAC
- UUID Version 6 usa os mesmos dados da v1, mas muda a ordem para que, ao ordenar, fique em ordem de geração
- UUID Version 7 é gerado com timestamp e dados aleatórios
-
UUIDs aleatórios e personalizados
- UUID Version 4 é gerado com dados totalmente aleatórios e se aproxima da forma que muita gente imagina quando pensa em UUID
- UUID Version 8 é totalmente personalizado, exceto pelos campos version/variant necessários em todas as versões
-
UUIDs baseados em hash dos dados de entrada
- UUID Version 3 é gerado a partir do hash MD5 dos dados fornecidos pelo usuário
- Entre os candidatos a valores de entrada na RFC estão DNS e URL
- UUID Version 5 é gerado a partir do hash SHA-1 dos dados fornecidos pelo usuário
- Assim como na v3, DNS e URL podem ser candidatos a entradas
- UUID Version 3 é gerado a partir do hash MD5 dos dados fornecidos pelo usuário
-
UUID reservado
- UUID Version 2 é reservado para IDs de segurança e não há detalhes conhecidos
Critérios práticos de escolha
- Na maioria dos casos, a escolha é v4 ou v7
- Se você precisa apenas de um ID aleatório, v4 é uma boa escolha padrão
- Se o ID precisa ser ordenável, v7 pode ser considerada
- Por exemplo, v7 pode ser candidata ao usar UUID como chave de banco de dados
- v5 ou v8 são mais indicadas quando se quer colocar dados próprios dentro do UUID
- Em geral, nesses casos o usuário já sabe que precisa desse tipo
- Segundo a RFC, v7 melhora v1 e v6, então, quando possível, deve-se usar v7 em vez de v1/v6
- Se v1 ou v6 for realmente necessária, v6 pode ser usada
- v2 é reservada para usos de segurança não especificados
- v3 foi substituída pela v5, que usa um hash mais forte, e é provável que quem precise da v3 já saiba disso
1 comentários
Opiniões no Hacker News
Dizer que não há detalhes sobre o UUID v2 só vale se você leu apenas o RFC notoriamente pouco claro: https://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#t...
Você quase nunca vai encontrá-lo, mas também existe o UUID version 0. Vale mencioná-lo porque ele é a origem dos bits reservados que permitiram que outras “versões” fossem definidas depois de forma compatível. Deixei a pesquisa relacionada organizada na minha biblioteca de UUID: https://github.com/okeeblow/DistorteD/blob/NEW%E2%80%85SENSA...
Resolvi dar suporte porque achei interessante, mas ainda preciso decidir como lidar com rollover de datas e com o formato mais antigo de UID do Apollo
Estou começando a trabalhar em um RFC informativo sobre os tipos históricos de UUID definidos no espaço de Variant 0-7, que deve ajudar as pessoas a entendê-los. Se quiser discutir ou revisar a redação, veja https://github.com/yocto/draft-yocto-uuid
Deu para encontrar os detalhes em 2 minutos. Clique no link do artigo para ir à parte de definição de DCE no RFC 9562, entre na especificação pelo primeiro link desse parágrafo e pesquise por “UUID” para chegar ao Apêndice A; está tudo lá
O nome é confuso, “Universal Unique Identifier”, mas o conteúdo necessário está todo ali. Seria bom ao menos clicar nos links que a própria pessoa colocou no texto
Pelo contexto, como as outras versões são descritas como geradas a partir de determinados elementos, essa frase claramente se refere à segunda coisa. A frase é um pouco ambígua, mas é difícil dizer que induz ao erro
Ainda assim, o apêndice foi interessante de ler, como um retrato daquele momento
Seria bom existir um padrão de UUID curto como
73WakrfVbNJBaAmhQtEeDvoubK7nP9xMTecnicamente, como poderia haver duplicidade em algum lugar, não seria um UUID, mas eu queria uma combinação padronizada de IDs aleatórios e curtos o bastante para memorizar
Acho que o motivo de não haver um padrão mais popular é que é preciso abrir mão de alguma coisa. 128 bits têm baixo risco de colisão para quase todos os usos, mas, quanto menor fica, mais é preciso considerar o contexto específico e o impacto das colisões, o que dificulta transformar isso em padrão. Usar outras codificações, como base64 ou base85, deixaria mais curto, mas sacrificaria coisas como distinção entre maiúsculas e minúsculas e segurança em URLs: https://github.com/ulid/spec
É apenas outra representação do mesmo UUID, e é reversível. No fim, um UUID é um valor de 128 bits, então é mais uma notação alternativa do que uma conversão real
Perde-se a vantagem de ordenação monotônica presente em algumas versões de UUID, mas base58 é segura para URLs e não inclui caracteres especiais. O valor ainda pode ser armazenado em binário. Por exemplo, no Postgres, dá para usar
byteaem vez de uma coluna de textoA discussão pode ser vista aqui: https://github.com/uuid6/new-uuid-encoding-techniques-ietf-d...
O timestamp do UUID v7 foi uma grande mudança para o Databend. Usamos isso para localizar rapidamente arquivos de metadados por timestamp no AWS S3, então operações como vacuum ficaram muito mais rápidas
PR: https://github.com/datafuselabs/databend/pull/16049
A grande vantagem dos UUIDs ordenados por tempo é melhorar a localidade. Ao inserir novos itens em um índice, geralmente a operação passa a ser anexar ao fim, o que pode ser mais barato do que inserções aleatórias. Por outro lado, também pode aumentar a contenção, então vale considerar um híbrido que coloque alguns bits aleatórios antes do timestamp para criar “shards” ordenados. As leituras também costumam se concentrar nos dados mais recentes, então é útil ter os dados recentes em um só lugar e bem aproveitados no cache
É difícil entender o objetivo do uuid2. Eu nem sabia que havia mais tipos assim, e vi uuid2 pela primeira vez quando pedi à Xandr a exclusão dos meus dados pessoais: https://news.ycombinator.com/item?id=40913915
Mesmo lendo a Wikipedia, não fica muito claro por que, depois de criar algo chamado “identificador universalmente único”, ainda existem vários tipos, e por que alguns deles foram originalmente feitos de modo a permitir rastrear até o PC. Fico me perguntando se misturar parte do código MAC torna o uuid2 mais próximo de aleatório, ou se há outro motivo. Do ponto de vista de privacidade, também me pergunto se não bastaria usar apenas identificadores longos com um conjunto enorme de caracteres possíveis, eliminando na prática a possibilidade de colisão
Quaisquer duas máquinas geravam o mesmo UID/UUID para os mesmos dois inputs, e quem recebesse a mensagem identificada conseguia reverter o identificador para seus componentes originais. Como foi projetado como rótulo para mensagens temporárias, as duas dimensões eram tempo e ID de hardware; no início usava-se o número de série da Apollo e, depois, coisas como o endereço de hardware Ethernet
Acho que boa parte da confusão vem do fato de que, na implementação inicial do AEGIS, engenheiros da Apollo começaram a usar UIDs “canned”, isto é, estáticos e bem conhecidos, para identificação no sistema de arquivos. Com o tempo, o uso comum do UUID mudou completamente: de identificador temporário em que colisões eram esperadas/intencionais para identificador canned em que colisões deveriam ser evitadas; e as duas dimensões viraram aleatoriedade e mais aleatoriedade
A história é mais complexa. A Microsoft contratou uma das pessoas centrais da Apollo para criar o MSRPC para o Windows NT, e foi assim que surgiu também o GUID. O GUID tem uma disposição de campos diferente da do UUID e, ao contrário do que muitos materiais dizem, não é mixed-endian. A Microsoft gosta de usar GUIDs canned não só para identificar mensagens RPC temporárias, mas também para praticamente qualquer coisa que precise de identificadores bem conhecidos, como classes COM, codecs de mídia etc. Ex.: https://gix.github.io/media-types/
Desculpem linkar meu repositório duas vezes na mesma seção de comentários, mas comecei a organizar essa história no README da minha biblioteca de UUID e preciso retomar isso. A Apollo começou em 1980 e o rascunho do RFC de UUID de Leach/Salz só apareceu em 1998, então há muita história que ficou de fora dos padrões modernos: https://github.com/okeeblow/DistorteD/blob/NEW%E2%80%85SENSA...
UUID v4 é apenas um gerador de bytes aleatórios com hífens em posições especificadas. Você não precisa necessariamente usá-lo; pode gerar seus próprios bytes aleatórios e economizar espaço
Também reduz coisas desnecessárias como hífens e informação de versão
É parecido com um endereço IPv4 ser um número de 32 bits, e “quatro grupos separados por pontos” ser uma de suas representações. Se você pensa em UUID como um formato de string, está errando já no conceito mais básico de UUID. Mesmo que você só queira um identificador aleatório, acho interessante haver pequenos bits de flag em um UUID aleatório dizendo “isto foi pensado para ser aleatório”. É útil quando você encontra um identificador isolado, sem contexto
Dá para discutir se é útil criar namespaces distintos entre vários métodos de geração, mas um gerador aleatório comum só tem 1/16 de chance de produzir um UUIDv4 válido. Claro que, se você quiser criar seu próprio gerador de UUID, definir os bits corretamente é algo trivial
Em Go, basta
uuid.New().String(), mas ler dados aleatórios comcrypto/rande convertê-los para base64 ou hex exige mais linhas e mais esforçoRecomendo não usar as versões baseadas em MAC. Em teoria, isso pode se aplicar a todas exceto v4 e v7, mas a v1 é a pior
A v3 também tem o problema de que o MD5 foi seriamente quebrado
Eu não conhecia os detalhes além da versão 4, mas o que parece realmente faltar e seria útil é um método usando dados SHA256 e um contador. Algo parecido com PBKDF2
Poderia ser um identificador derivado que preserva a privacidade e também permitiria provar de forma flexível que um determinado UUID foi derivado de uma certa semente
Fora isso, você provavelmente vai querer uma saída mais longa
É só usar v7
Agora é a vez dos especialistas em segurança dizerem que não
Em muitos usos, seria muito útil conseguir gerar o mesmo ID ao reprocessar os dados, mas não conheço uma forma padrão de fazer isso