Generazione di un identificatore univoco globale in Java
-
08-07-2019 - |
Domanda
Riepilogo: sto sviluppando un'applicazione Web Java persistente e devo assicurarmi che tutte le risorse che persisto abbiano identificatori univoci a livello globale per evitare duplicati.
La stampa fine:
- Non sto usando un RDBMS, quindi non ho generatori di sequenze fantasiose (come quello fornito da Oracle)
- Vorrei che fosse veloce, preferibilmente tutto in memoria - Preferirei non dover aprire un file e aumentare un po 'di valore
- Deve essere thread-safe (sto anticipando che solo una JVM alla volta dovrà generare ID)
- Deve esserci coerenza tra le istanze della JVM. Se il server si arresta e si avvia, il generatore di ID non dovrebbe rigenerare gli stessi ID che ha generato nelle precedenti istanze (o almeno la possibilità deve essere davvero, molto sottile - prevedo molti milioni di risorse preesistenti)
- Ho visto gli esempi nell'articolo modello ID univoco EJB. Non funzioneranno per me (preferirei non fare affidamento esclusivamente su System.currentTimeMillis () perché persisteremo risorse multiple per millisecondo).
- Ho esaminato le risposte proposte in questo domanda . La mia preoccupazione per loro è: qual è la possibilità che ottengo un ID duplicato nel tempo? Sono incuriosito dal suggerimento di utilizzare java .util.UUID per un UUID , ma ancora una volta, le possibilità di un duplicato deve essere infinitamente piccolo.
- Sto usando JDK6
Soluzione
Gli UUID abbastanza sicuri sono " abbastanza buono " ;. Ci sono 340.282.366.920.938.463.463.374.607.431.770.000.000 UUID disponibili.
http://www.wilybeagle.com/guid_store/guid_explain.htm
" Per mettere in prospettiva questi numeri, si stima che il rischio annuale di essere colpiti da un meteorite sia una possibilità su 17 miliardi, il che significa che la probabilità è di circa 0,00000000006 (6 & # 215; 10 & # 8722; 11), equivalente alla probabilità di creare alcune decine di trilioni di UUID in un anno e di avere un duplicato. In altre parole, solo dopo aver generato 1 miliardo di UUID ogni secondo per i prossimi 100 anni, la probabilità di creare un solo duplicato sarebbe di circa il 50%. La probabilità di un duplicato sarebbe di circa il 50% se ogni persona sulla terra possiede 600 milioni di UUID & Quot;
Altri suggerimenti
public class UniqueID {
private static long startTime = System.currentTimeMillis();
private static long id;
public static synchronized String getUniqueID() {
return "id." + startTime + "." + id++;
}
}
Se deve essere univoco per PC: probabilmente potresti utilizzare (System.currentTimeMillis() << 4) | (staticCounter++ & 15)
o qualcosa del genere.
Ciò ti consentirebbe di generare 16 per ms. Se hai bisogno di più, sposta di 5 e poi con 31 ...
se deve essere univoco su più PC, è necessario combinare anche l'indirizzo MAC della scheda di rete principale.
modifica: per chiarire
private static int staticCounter=0;
private final int nBits=4;
public long getUnique() {
return (currentTimeMillis() << nBits) | (staticCounter++ & 2^nBits-1);
}
e modifica nBits nella radice quadrata del numero più grande che dovresti generare per ms.
Alla fine passerà sopra. Probabilmente 20 anni o qualcosa del genere con nBits a 4.
Dalla memoria i pacchetti remoti RMI contengono un generatore UUID. Non so se valga la pena esaminarlo.
Quando ho dovuto generarli, di solito utilizzo un hashsum MD5 della data e ora correnti, il nome utente e l'indirizzo IP del computer. Fondamentalmente l'idea è quella di prendere tutto ciò che puoi scoprire sul computer / persona e quindi generare un hash MD5 di queste informazioni.
Funziona davvero bene ed è incredibilmente veloce (una volta inizializzato MessageDigest per la prima volta).
perché non fare così
String id = Long.toString(System.currentTimeMillis()) +
(new Random()).nextInt(1000) +
(new Random()).nextInt(1000);
se si desidera utilizzare un'implementazione più breve e più veloce a cui l'UUID java dà un'occhiata:
vedi le scelte e le limitazioni di implementazione nel javadoc.
ecco un test unitario su come usare: