23 pontos por kunggom 2022-02-24 | 15 comentários | Compartilhar no WhatsApp

Quando pensamos em como criar um ID que identifique de forma única um determinado recurso, pelo que sei normalmente usamos principalmente duas abordagens. Uma é aproveitar diretamente o valor inteiro sequencial gerado ao configurar Auto Increment na chave primária de uma tabela do banco de dados; a outra é gerar e usar, a cada vez, um GUID aleatório de 128 bits (também chamado de UUID).

Grande parte dos dados dos inúmeros serviços que vemos na web é gerenciada por RDBMS, e o Auto Increment desses bancos não só é bastante otimizado internamente, como também é fácil de entender e prever do ponto de vista de quem desenvolve. Além disso, também é simples ordenar os dados pela sequência em que entraram. Afinal, é só ir somando 1 ao número. Mas esse método pode ter desvantagens em certos casos, como expor externamente informações que seria melhor não revelar por questões de segurança (por exemplo, um concorrente pode perceber com facilidade indicadores importantes, como o número de usuários do nosso serviço), ou causar problemas em uma arquitetura distribuída.

O uso de GUID tem características praticamente opostas às disso. Como o GUID gera e usa, a cada momento, um valor de 128 bits praticamente único, com chance de colisão próxima de zero e sem depender de outros elementos, ele não traz problema algum em arquiteturas distribuídas e também evita o risco de vazar para fora algum significado útil adicional. Porém, gravar valores gerados aleatoriamente em um RDBMS pode causar perda de desempenho e, além disso, por si só, também é impossível ordenar os dados pela sequência em que foram inseridos. Para compensar essa fraqueza, às vezes se usa algo como o Timeflake, que não é totalmente aleatório e incorpora informação de tempo para ter uma sequencialidade imperfeita. Nunca usei isso diretamente, mas ouvi dizer que frameworks como o Laravel também adotam esse tipo de abordagem.

Pessoalmente, como na empresa em que trabalho hoje desenvolvemos produtos integrados com serviços que usam GUID de forma intensa, como o Office 365 e a Graph API da Microsoft, passei a achar que uma abordagem que faz uso ativo de GUID também pode ser bem interessante. Mas, no fim, esse tipo de escolha depende de onde e para que será usado, então é bom conhecer com clareza os prós e contras de cada método. Por isso, apresento um fio de tweets com o diário fictício de um desenvolvedor de serviços sobre esse tema. (coreano)

15 comentários

 
kunggom 2022-04-22

Recentemente, ocorreu um caso de uso fraudulento no Shinhan Card e, em relação a isso, foi confirmado o risco de essa administradora ficar exposta a uso fraudulento vindo do exterior por emitir números de cartão de crédito de forma sequencial.
Mudaram só um pouco o número e "pagou"… cartões de crédito expostos a roubo de dados
Serviço de Supervisão Financeira busca medidas para casos recentes de uso fraudulento no Shinhan Card

 
kunggom 2022-02-24

Graças aos comentários de vocês, acabei aprendendo bastante coisa que eu não conhecia bem.
Por causa disso, também conheci pela primeira vez coisas como Hashids, Nano ID e a abordagem usada pelo Instagram.

 
ehlegeth 2022-02-24

A motivação é parecida com a do ulid, mas como havia um Internet-Draft em proposta, eu usei essa especificação em um projeto anterior.
https://github.com/uuid6/uuid6-ietf-draft

Sistemas de ID criados dessa forma aparecem com frequência, e acho que já chegou o momento de pelo menos unificar em um só os que são do tipo UUID-like.

 
kunggom 2022-02-24

Mas dizem que tentar unificar em um só os padrões que proliferam por aí criando um novo padrão geralmente só coloca mais um candidato na competição no mercado. kkkkk
https://xkcd.com/927/

 
ehlegeth 2022-03-02

Pois é haha, então parece que todo mundo acaba propondo novos IDs.

 
nallwhy 2022-02-24

O Gyuwon compartilhou isso há algum tempo, mas na verdade não é uma questão simples, não é?
https://byterot.blogspot.com/2013/02/…

 
roxie 2022-02-24

Eu também quero uma explicação adicional sobre essa ideia de que é um "problema simples"

 
ehlegeth 2022-02-24

Em que sentido você está dizendo que é um problema simples?

Neste texto, ele diz: 'With storage nowadays very cheap, this normally is not a problem from the storage point of view.', mas há casos em que esse ID precisa circular pela rede, ou precisa atuar como chave na memória, ou é uma chave usada em vários lugares com grande volume de dados; então, quando é importante economizar mesmo que sejam apenas alguns bytes, parece haver situações em que é necessário rejeitar o uso de UUID dependendo do contexto.

 
nallwhy 2022-02-25

O problema mencionado neste texto é a degradação de desempenho que ocorre ao usar valores gerados aleatoriamente como primary key
(se há outro problema sendo mencionado e eu não percebi, por favor me avisem)
esse problema já tem resposta. É o mesmo problema da paginação baseada em cursor em ordem cronológica, então imagino que muita gente já tenha resolvido isso.

 
nallwhy 2022-02-25

Também fico curioso sobre em que sentido isso seria um problema complexo.
Como você disse que, na situação mencionada, a proposta deveria ser recusada, parece ser uma questão simples...
Problema complexo não é justamente quando não se consegue tomar uma decisão nem para um lado nem para o outro?

 
ehlegeth 2022-03-02

Perguntei porque a expressão "problema simples" pode ser interpretada de várias formas, então fiquei curioso sobre em que sentido você a usou. Se queria dizer que o problema em si não é difícil, ou que há uma resposta clara (?) apresentada no texto, o que deixa pouco espaço para reflexão, por exemplo.
Quanto ao primeiro caso, como mencionei acima, dependendo da situação pode haver casos em que o ID precise ser usado também fora do banco de dados, então há muitos fatores a considerar e não acho que seja um problema simples.

 
yolatengo 2022-02-24

No ecossistema Python/Django também tem isto: https://pypi.org/project/django-hashid-field/1.0.0/

 
kunggom 2022-02-24

Oh, então também existe um método chamado Hashids.
Se o salt vazar, pode surgir o problema de exposição externa das informações mencionadas no texto acima, mas ainda assim acho que é um bom método.

 
majorika 2022-02-24

Também existe o ULID. 128 bits, ordenável cronologicamente.
https://github.com/ulid/spec

 
kunggom 2022-02-24

Vendo como há tantas coisas com aparências tão parecidas, talvez o pensamento das pessoas quase sempre acabe chegando ao mesmo lugar…?