2013-08-14 35 views
9

Ho bisogno di generare un ID univoco di 10 cifre in Java. Queste sono le restrizioni per questo ID:Java: ID univoco di 10 cifre

  • Solo numerici
  • massima di 10 cifre
  • possibile creare fino a 10 diversi ID al secondo
  • deve essere unico (anche se l'applicazione riparte)
  • Non è possibile salvare un numero nel database
  • il più veloce possibile non aggiungere molto lattency al sistema

La soluzione migliore che ho trovato finora è la seguente:

private static int inc = 0; 

private static long getId(){ 

    long id = Long.parseLong(String.valueOf(System.currentTimeMillis()) 
      .substring(1,10) 
      .concat(String.valueOf(inc))); 
    inc = (inc+1)%10; 
    return id; 
} 

Questa soluzione presenta i seguenti problemi:

  • Se per qualsiasi motivo non v'è la necessità di creare più di 10 ID per seccond questa soluzione non funzionerà
  • In circa 32 anni questo ID potrebbe essere ripetuto (questo è probabilmente accettabile)

Qualsiasi altra soluzione per creare questo ID?

Qualsiasi altro problema non ho pensato con il mio?

Grazie per il vostro aiuto,

+1

È possibile eseguire contemporaneamente più istanze dell'applicazione? – assylias

+0

Al momento è in esecuzione una sola istanza, ma potrebbe essere possibile in futuro. Abbiamo anche un'istanza secondaria nel caso in cui il primario vada giù, ma solo uno di essi (primario o secondario) verrebbe eseguito nello stesso momento. – magodiez

+0

Come indicato in alcune delle risposte seguenti, la mia implementazione fallirà in ambiente multi-istanza o multi-threading, quindi supponiamo che una singola istanza con un singolo thread sarà in esecuzione. – magodiez

risposta

7

Questo è un piccolo miglioramento per la tua, ma dovrebbe essere resiliente.

private static final long LIMIT = 10000000000L; 
private static long last = 0; 

public static long getID() { 
    // 10 digits. 
    long id = System.currentTimeMillis() % LIMIT; 
    if (id <= last) { 
    id = (last + 1) % LIMIT; 
    } 
    return last = id; 
} 

Così com'è, dovrebbe gestire fino a 1000 al secondo con una frequenza di ciclo relativamente breve.Per estendere la frequenza del ciclo (ma abbreviare la risoluzione) è possibile utilizzare (System.currentTimeMillis()/10) % 10000000000L o (System.currentTimeMillis()/100) % 10000000000L.

+1

Probabilmente è una buona idea renderlo thread-safe. – assylias

+0

L'uso di (System.currentTimeMillis()/100) risolverà il problema se più di 10 ID devono essere creati nello stesso secondo, poiché questo non sarà mai qualcosa di continuo. Grazie,;) – magodiez

+0

Ricorda che 'System.currentTimeMillis()' ha una risoluzione minima. L'ho trovato a circa 15ms sui sistemi MS, quindi '/ 100' potrebbe non essere fluido come pensi, anche se questo algoritmo lo tratterà per te. – OldCurmudgeon

2

questo può essere una pazza idea, ma la sua idea :).

  • Prima generare UUID e ottenere una rappresentazione di stringa con java.util.UUID.randomUUID().toString()
  • seconda convertire stringa generata al byte matrice (byte[])

  • Poi convertirlo lungo buffer: java.nio.ByteBuffer.wrap(byte digest[]).asLongBuffer().get()

  • Tronca a 10 cifre

Non sono sicuro dell'unicità di quell'approccio che, so che si può fare affidamento sull'unicità degli UUID, ma non abbiamo verificato quanto siano unici convertiti e troncati a un numero lungo di 10 cifre.

L'esempio è stato preso da JavaRanch, forse c'è dell'altro.

Edit: Come si sono limitati a 10 cifre forse semplice generatore casuale sarebbe abbastanza per voi, date un'occhiata in quella quesion/risposte su SO: Java: random long number in 0 <= x < n range

+0

[Gli UUID non * sono * garantiti come unici] (http://stackoverflow.com/questions/5728205/is-unique-id-generation-using-uuid-really-unique). Anche se la probabilità di ottenere due UUID identici è molto piccola. – assylias

+1

Esattamente, ma come ho scritto 'puoi fare affidamento sulla loro unicità', non che siano unici :) – Kris

0

Che significa che deve essere unico? Anche tra più istanze attualmente in esecuzione? Rompe la tua implementazione.

Se deve essere univoco in tutto l'universo, la soluzione migliore è utilizzare UUID come generatore di identificatori matematicamente provato poiché genera un valore univoco per universo. Il numero meno accurato ti porta a scontri.

Quando c'è una sola istanza simultanea, è possibile prendere il tempo corrente in millisecure e risolvere il problema di 10 ms utilizzando l'incremento. Se si sacrifica il numero corretto di ultime posizioni nel numero, è possibile ottenere molti numeri entro un millisecondo. Definirei la precisione: intendo quanti numeri unici avete bisogno per secondi. Risolvi il problema senza alcuna persistenza con questo approccio.

0

statico privato AtomicoRiferimento currentTime = new AtomicReference <> (System.currentTimeMillis());

public static Long nextId() { 
    return currentTime.accumulateAndGet(System.currentTimeMillis(), (prev, next) -> next > prev ? next : prev + 1) % 10000000000L; 
} 
+0

Per favore, modifica la tua risposta per formattare correttamente il codice. Inoltre, aggiungi qualche spiegazione – Garf365