13 Stimmen

Generierung eines global eindeutigen Bezeichners in Java

Zusammenfassung: Ich entwickle eine persistente Java-Webanwendung, und ich muss sicherstellen, dass alle Ressourcen, die ich persistiere, global eindeutige Bezeichner haben, um Duplikate zu vermeiden.

Das Kleingedruckte:

  1. Ich verwende kein RDBMS, also habe ich auch keine ausgefallenen Sequenzgeneratoren (wie z. B. den von Oracle)
  2. Ich möchte, dass es schnell geht, vorzugsweise alles im Speicher - ich möchte nicht erst eine Datei öffnen und einen Wert inkrementieren müssen
  3. Es muss thread-sicher sein (ich gehe davon aus, dass nur eine JVM zur gleichen Zeit IDs generieren muss)
  4. Es muss Konsistenz zwischen den Instanzen der JVM bestehen. Wenn der Server heruntergefahren und wieder hochgefahren wird, sollte der ID-Generator nicht dieselben IDs neu generieren, die er in früheren Instanzierungen generiert hat (oder zumindest muss die Wahrscheinlichkeit sehr, sehr gering sein - ich rechne mit vielen Millionen vorhandener Ressourcen)
  5. Ich habe die Beispiele in dem Artikel EJB unique ID pattern gesehen. Sie werden für mich nicht funktionieren (ich möchte mich nicht ausschließlich auf System.currentTimeMillis() verlassen, da wir mehrere Ressourcen pro Millisekunde persistieren werden).
  6. Ich habe mir die Antworten angesehen, die in diese Frage . Ich frage mich, wie groß die Wahrscheinlichkeit ist, dass ich mit der Zeit eine doppelte ID erhalte. Ich bin fasziniert von dem Vorschlag, die java.util.UUID für eine UUID Aber auch hier gilt, dass die Wahrscheinlichkeit eines Duplikats verschwindend gering sein muss.
  7. Ich verwende JDK6

33voto

Shawn Miller Punkte 7007

Ziemlich sicher sind UUIDs "gut genug". Es sind 340.282.366.920.938.463.463.374.607.431.770.000.000 UUIDs verfügbar.

http://www.wilybeagle.com/guid_store/guid_explain.htm

"Um diese Zahlen in die richtige Perspektive zu rücken: Das jährliche Risiko, von einem Meteoriten getroffen zu werden, wird auf eine Chance von 17 Milliarden geschätzt, d. h. die Wahrscheinlichkeit beträgt etwa 0,00000000006 (6 × 1011), was der Wahrscheinlichkeit entspricht, in einem Jahr einige zehn Billionen UUIDs zu erzeugen und ein Duplikat zu haben. Mit anderen Worten: Nur wenn in den nächsten 100 Jahren jede Sekunde 1 Milliarde UUIDs erzeugt werden, beträgt die Wahrscheinlichkeit, dass nur ein einziges Duplikat entsteht, etwa 50 %. Die Wahrscheinlichkeit eines Duplikats wäre etwa 50 %, wenn jeder Mensch auf der Erde 600 Millionen UUIDs besitzt.

http://en.wikipedia.org/wiki/Universally_Unique_Identifier

1voto

Bill K Punkte 61074

Wenn es pro PC eindeutig sein muss: Sie können wahrscheinlich (System.currentTimeMillis() << 4) | (staticCounter++ & 15) oder so ähnlich.

Damit könnten Sie 16 pro ms erzeugen. Wenn Sie mehr brauchen, verschieben Sie um 5 und dann mit 31...

Wenn sie für mehrere PCs eindeutig sein muss, sollten Sie auch die MAC-Adresse Ihrer primären Netzwerkkarte eingeben.

edit: zur Klarstellung

private static int staticCounter=0;
private final int nBits=4;
public long getUnique() {
    return (currentTimeMillis() << nBits) | (staticCounter++ & 2^nBits-1);
}

und ändern Sie nBits in die Quadratwurzel der größten Zahl, die Sie pro ms erzeugen müssen.

Sie wird schließlich umkippen. Wahrscheinlich 20 Jahre oder so mit nBits bei 4.

1voto

Dave Griffiths Punkte 1813
public class UniqueID {
    private static long startTime = System.currentTimeMillis();
    private static long id;

    public static synchronized String getUniqueID() {
        return "id." + startTime + "." + id++;
    }
}

0voto

Aidos Punkte 2685

Soweit ich mich erinnere, enthalten die RMI-Remote-Pakete einen UUID-Generator. Ich weiß nicht, ob es sich lohnt, das zu prüfen.

Wenn ich sie generieren muss, verwende ich in der Regel eine MD5-Hashsumme aus dem aktuellen Datum, der Uhrzeit, dem Benutzernamen und der IP-Adresse des Computers. Im Grunde genommen geht es darum, alles, was man über den Computer/die Person herausfinden kann, zu nehmen und dann einen MD5-Hash über diese Informationen zu erstellen.

Es funktioniert wirklich gut und ist unglaublich schnell (sobald Sie den MessageDigest zum ersten Mal initialisiert haben).

0voto

kem Punkte 11

Warum nicht so

String id = Long.toString(System.currentTimeMillis()) + 
    (new Random()).nextInt(1000) + 
    (new Random()).nextInt(1000);

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X