Wahrscheinlichkeit einer Kollision mit den wichtigsten Teilen einer UUID in Java
Frage
Wenn ich benutze Long uuid = UUID.randomUUID().getMostSignificantBits()
Wie wahrscheinlich ist es, eine Kollision zu bekommen. Es schneidet die am wenigsten bedeutenden Teile ab, sodass Sie eine Kollision begegnen können, oder?
Lösung
Entsprechend die Dokumentation, die statische Methode UUID.randomUUID()
generiert einen Typ 4 UUID.
Dies bedeutet, dass sechs Bits für einige Typinformationen verwendet werden und die verbleibenden 122 Bit zufällig zugeordnet sind.
Die sechs nicht randomischen Bits sind mit vier in der bedeutendsten Hälfte der UUID und zwei in der am wenigsten signifikanten Hälfte verteilt. Die bedeutendste Hälfte Ihres UUID enthält also 60 Bit Zufälligkeit, was bedeutet, dass Sie im Durchschnitt 2^30 Uuids erzeugen müssen, um eine Kollision zu erhalten (verglichen mit 2^61 für die volle UUID).
Also würde ich sagen, dass Sie ziemlich sicher sind. Beachten Sie jedoch, dass dies für andere Arten von UUIDs absolut nicht zutrifft, wie Carl Seleborg erwähnt.
Übrigens wären Sie etwas besser dran, indem Sie die am wenigsten signifikante Hälfte der UUID verwenden (oder nur eine zufällige Länge mit Securerandom generieren).
Andere Tipps
Raymond Chen hat einen wirklich exzellenten Blog -Beitrag dazu:
Guids sind weltweit einzigartig, aber Unterstrings von Guids sind nicht
Ich denke, dies ist das beste Beispiel für die Verwendung von Randomuuid:
Sie sind besser dran, nur einen zufälligen langen Wert zu generieren, dann sind alle Bits zufällig. In Java 6 verwendet New Random () das System.nanotime () plus einen Zähler als Samen.
Es gibt unterschiedliche Einzigartigkeitsniveaus.
Wenn Sie über viele Maschinen eindeutig sind, können Sie eine zentrale Datenbanktabelle für die Zuweisung von eindeutigen IDs oder sogar für die einzigartigen IDs haben.
Wenn Sie nur die Einzigartigkeit in einer App haben müssen, können Sie nur einen Zähler haben (oder einen Zähler, der von CurrentTimemillis ()*1000 oder Nanotime () abhängig von Ihren Anforderungen startet).
Zeit nutzen YYYYDDDD
(Jahr + Jahr des Jahres) als Präfix. Dies verringert die Datenbankfragmentierung in Tabellen und Indizes. Diese Methode kehrt zurück byte[40]
. Ich habe es in einer hybriden Umgebung verwendet, in der das Active Directory SID (varbinary(85)
) ist der Schlüssel für LDAP-Benutzer und eine von automatisch generierte ID für Nicht-LDAP-Benutzer wird für Nicht-LCAP-Benutzer verwendet. Auch die große Anzahl von Transaktionen pro Tag in Transaktionstabellen (Bankenindustrie) kann den Standard nicht verwenden Int
Typen für Schlüssel
private static final DecimalFormat timeFormat4 = new DecimalFormat("0000;0000");
public static byte[] getSidWithCalendar() {
Calendar cal = Calendar.getInstance();
String val = String.valueOf(cal.get(Calendar.YEAR));
val += timeFormat4.format(cal.get(Calendar.DAY_OF_YEAR));
val += UUID.randomUUID().toString().replaceAll("-", "");
return val.getBytes();
}