Gerando um identificador exclusivo em Java
-
08-07-2019 - |
Pergunta
Resumo:. Estou desenvolvendo uma aplicação web persistente Java, e eu preciso ter certeza de que todos os recursos que persistem têm identificadores exclusivos globalmente para evitar duplicatas
O Fine Print:
- Não estou usando um RDBMS, então eu não tem nenhum geradores de seqüência de fantasia (como o fornecido pela Oracle)
- Eu gostaria que ele seja rápido, de preferência todos na memória - Eu prefiro não ter de abrir um arquivo e incremento de algum valor
- Ele precisa ser thread-safe (estou antecipando que apenas uma JVM em um momento será necessário gerar IDs)
- É preciso haver consistência entre instâncias da JVM. Se os fecha servidor para baixo e começa acima, o gerador de ID não deve voltar a gerar os mesmos IDs que gerou em instâncias anteriores (ou pelo menos a chance tem que ser muito, muito magro - Prevejo muitos milhões de recursos presisted)
- Eu vi os exemplos no artigo padrão ID EJB único. Eles não vai funcionar para mim (eu prefiro não depender exclusivamente dos System.currentTimeMillis () porque vamos estar persistindo vários recursos por milissegundo).
- Eu olhei as respostas propostas no este questionar . A minha preocupação sobre eles é, qual é a chance que eu vou conseguir um ID duplicado ao longo do tempo? Estou intrigado com a sugestão de usar java .util.UUID por UUID , mas novamente, as chances de uma duplicata necessidade de ser infinitamente pequeno.
- Eu estou usando JDK6
Solução
UUIDs certeza bonitas são "suficientemente bom". Há 340,282,366,920,938,463,463,374,607,431,770,000,000 UUIDs disponível.
http://www.wilybeagle.com/guid_store/guid_explain.htm
"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 mil milhões, o que significa a probabilidade é de cerca de 0,00000000006 (6 × 10-11), equivalente às chances de criando algumas dezenas de trilhões de UUIDs em um ano e ter um duplicado. em outras palavras, somente depois de gerar 1 bilhão de UUIDs a cada segundo para os próximos 100 anos, a probabilidade de criar apenas uma duplicata seria cerca de 50%. a probabilidade de uma duplicata seria cerca de 50%, se cada pessoa na terra possui 600 milhões UUIDs "
Outras dicas
public class UniqueID {
private static long startTime = System.currentTimeMillis();
private static long id;
public static synchronized String getUniqueID() {
return "id." + startTime + "." + id++;
}
}
Se ele precisa ser único por PC:. Você provavelmente poderia usar (System.currentTimeMillis() << 4) | (staticCounter++ & 15)
ou algo parecido
Isso permitiria que você para gerar 16 por ms. Se precisar de mais, turno por 5 e e-lo com 31 ...
se ele precisa ser exclusivo em vários PCs, você também deve combinar o endereço MAC da placa de rede primária.
Edit: Para esclarecer
private static int staticCounter=0;
private final int nBits=4;
public long getUnique() {
return (currentTimeMillis() << nBits) | (staticCounter++ & 2^nBits-1);
}
e altere nBits à raiz quadrada do maior número, caso haja necessidade de gerar por ms.
Ele acabará por rolar. Provavelmente 20 anos ou algo com nBits a 4.
Da memória os pacotes remotos RMI conter um gerador de UUID. Eu não sei se isso é pena olhar em.
Quando eu tive para gerá-los Eu normalmente uso um hashsum MD5 do tempo data atual, o nome do usuário eo endereço IP do computador. Basicamente, a idéia é fazer tudo o que você pode descobrir mais sobre o computador / pessoa e, em seguida, gerar um hash MD5 desta informação.
Ele funciona muito bem e é incrivelmente rápido (uma vez que você inicializa o MessageDigest pela primeira vez).
Por que não fazer como este
String id = Long.toString(System.currentTimeMillis()) +
(new Random()).nextInt(1000) +
(new Random()).nextInt(1000);
Se você quiser usar um mais curto e mais rápido de implementação que java UUID dar uma olhada em:
ver as opções de implementação e limitações no javadoc.
aqui é um teste de unidade sobre como usar: