2013-08-14 17 views
9

Ich muss eine eindeutige 10-stellige ID in Java generieren. Dies sind die Einschränkungen für diese ID:Java: Eindeutige 10-stellige ID

  • nur numerische
  • maximal 10 Ziffern
  • möglich schaffen bis zu 10 verschiedene IDs pro Sekunde
  • muss eindeutig sein (auch wenn die Anwendung Neustarts)
  • nicht möglich, eine Nummer in der Datenbank
  • so schnell wie möglich speichern nicht viel lattency an dem System
hinzufügen

Die beste Lösung, die ich bisher gefunden ist folgende:

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; 
} 

Diese Lösung hat die folgenden Probleme:

  • Wenn aus irgendeinem Grund gibt es einen Bedarf von mehr als 10 IDs pro seccond zu erstellen ist , diese Lösung wird nicht funktionieren.
  • In etwa 32 Jahren werden diese ID wiederholt werden kann (Dies ist wahrscheinlich akzeptabel)

Jede andere Lösung, um diese ID zu erstellen?

Irgendein anderes Problem, an das ich bei meinem nicht gedacht habe?

Danke für Ihre Hilfe,

+1

Können mehrere Instanzen der Anwendung gleichzeitig ausgeführt werden? – assylias

+0

Momentan läuft nur eine Instanz, ist aber möglicherweise in Zukunft möglich. Wir haben auch eine Sekundärinstanz für den Fall, dass die Primärseite ausfällt, aber nur eine von ihnen (primär oder sekundär) gleichzeitig ausgeführt wird. – magodiez

+0

Wie in einigen der folgenden Antworten gezeigt, wird meine Implementierung in Umgebungen mit mehreren Instanzen oder mehreren Threads fehlschlagen. Nehmen wir an, dass eine einzelne Instanz mit einem einzigen Thread ausgeführt wird. – magodiez

Antwort

7

Dies ist eine kleine Verbesserung zu Ihnen, aber sollte belastbar sein.

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; 
} 

Wie es ist sollte es bis zu 1000 pro Sekunde mit einer vergleichsweise kurzen Zyklusrate verwalten.Um die Zyklusrate zu verlängern (aber die Auflösung zu verkürzen), können Sie (System.currentTimeMillis()/10) % 10000000000L oder (System.currentTimeMillis()/100) % 10000000000L verwenden.

+1

Es ist wahrscheinlich eine gute Idee, es auch threadsicher zu machen. – assylias

+0

Die Verwendung von (System.currentTimeMillis()/100) löst das Problem tatsächlich, wenn mehr als 10 IDs in der gleichen Sekunde erstellt werden müssen, da dies niemals etwas Kontinuierliches sein wird. Danke,;) – magodiez

+0

Denken Sie daran, dass 'System.currentTimeMillis()' eine minimale Auflösung hat. Ich habe festgestellt, dass es auf MS-Systemen um etwa 15 ms läuft, so dass '/ 100' nicht so flüssig ist, wie Sie denken, obwohl dieser Algorithmus das für Sie übernimmt. – OldCurmudgeon

2

Dies ist eine verrückte Idee sein kann, aber es ist eine Idee :).

  • Erste UUID erzeugen und eine String-Darstellung mit java.util.UUID.randomUUID().toString()
  • Zweite convert erzeugt Zeichenfolge erhalten auf Byte-Array (byte[])

  • Dann wandeln sie in langen Puffer: java.nio.ByteBuffer.wrap(byte digest[]).asLongBuffer().get()

  • Abschneiden auf 10 Ziffern

Nicht sicher über die Eindeutigkeit dieses Ansatzes tho, ich weiß, dass Sie sich auf die Eindeutigkeit von UUIDs verlassen können, aber nicht überprüft haben, wie einzigartig sie konvertiert und auf 10 Ziffern lange Zahl gekürzt werden.

Beispiel wurde von JavaRanch genommen, vielleicht gibt es mehr.

Edit: Wie Sie auf 10 Stellen begrenzt sind vielleicht einfach Zufallsgenerator wäre genug für Sie, haben Sie einen Blick in diese quesion/Antworten auf SO: Java: random long number in 0 <= x < n range

+0

[UUIDs sind * nicht * garantiert einzigartig] (http://stackoverflow.com/questions/5728205/is-unique-id-generation-using-uuid-really-unique). Obwohl die Wahrscheinlichkeit, zwei identische UUID zu erhalten, sehr gering ist. – assylias

+1

Genau, aber wie ich schrieb "Sie können sich auf ihre Einzigartigkeit verlassen", nicht dass sie einzigartig sind :) – Kris

0

Was bedeutet, dass es einzigartig sein muss? Sogar über mehr aktuell laufende Instanzen? Es bricht Ihre Implementierung.

Wenn es im gesamten Universum eindeutig sein muss, ist die beste Lösung, UUID als mathematisch bewiesenen Bezeichnergenerator zu verwenden, da es einen eindeutigen Wert pro Universum generiert. Weniger genaue Anzahl bringt Sie zu Kollisionen.

Wenn es nur eine gleichzeitige Instanz gibt, können Sie die aktuelle Zeit in Millis nehmen und 10ms Problem mit Inkrementierung lösen. Wenn Sie die richtige Anzahl der letzten Positionen in der Zahl opfern, können Sie innerhalb eines Millisekunden viele Zahlen erhalten. Ich würde dann die Präzision definieren - ich meine, wie viele eindeutige Zahlen brauchen Sie pro Sekunde. Sie werden das Problem ohne jede Persistenz mit diesem Ansatz lösen.

0

private statische AtomicReference currentTime = neue AtomicReference <> (System.currentTimeMillis());

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

Bitte, bearbeiten Sie Ihre Antwort, um den Code korrekt zu formatieren. Fügen Sie auch eine Erklärung hinzu – Garf365