Jeśli używam Long uuid = UUID.randomUUID().getMostSignificantBits()
, to jak prawdopodobne jest zderzenie. Odcina najmniej znaczące bity, więc istnieje możliwość, że wpadniesz w kolizję, prawda?Prawdopodobieństwo kolizji przy użyciu najbardziej znaczących bitów UUID w Javie
Odpowiedz
Według the documentation statyczna metoda UUID.randomUUID()
generuje typ 4 UUID.
Oznacza to, że w przypadku niektórych informacji o typie użytych jest sześć bitów, a pozostałe 122 są przydzielane losowo.
Sześć nieliniowych bitów jest rozłożonych czterema w najbardziej znaczącej połowie UUID, a dwie w najmniej znaczącej połowie. Tak więc najważniejsza połowa twojego UUID zawiera 60 bitów losowości, co oznacza, że musisz średnio wygenerować 2^30 identyfikatorów UUID, aby uzyskać kolizję (w porównaniu do 2^61 dla pełnego UUID).
Powiedziałbym więc, że jesteś raczej bezpieczny. Należy jednak zauważyć, że jest to absolutnie nieprawdą w przypadku innych typów UUID, o czym wspomina Carl Seleborg.
Nawiasem mówiąc, lepiej byłoby, gdybyś użył najmniej znaczącej połowy UUID (lub po prostu wygenerował losowo długą używając SecureRandom).
Raymond Chen ma naprawdę doskonałą blogu na ten temat:
Link jest martwy. – Zero3
Link nie jest już martwy. –
Lepszym wyjściem jest generowanie losowej długiej wartości, a następnie wszystkie bity są losowe. W Javie 6, nowy losowy() używa System.nanoTime() plus licznik jako nasienie.
Istnieją różne poziomy unikalności.
Jeśli potrzebujesz wyjątkowości na wielu komputerach, możesz mieć centralną tabelę bazy danych do przydzielania niepowtarzalnych identyfikatorów, a nawet partii niepowtarzalnych identyfikatorów.
Jeśli wystarczy mieć unikatowości w jednej aplikacji może po prostu masz licznik (lub licznik, który zaczyna się od currentTimeMillis() * 1000 lub nanoTime() w zależności od potrzeb)
I uważa, że to najlepszym przykładem korzystania randomUUID:
Zastosowanie Czas YYYYDDDD
(rok + dzień roku) jako prefiks. Zmniejsza to fragmentację bazy danych w tabelach i indeksach. Ta metoda zwraca byte[40]
. Używałem go w środowisku hybrydowym, w którym identyfikator SID usługi Active Directory (varbinary(85)
) jest kluczem dla użytkowników LDAP, a identyfikator generowany automatycznie dla aplikacji jest używany dla użytkowników innych niż LDAP. Również duża liczba transakcji dziennie w tabelach transakcyjnych (sektor bankowy) nie można używać standardowych Int
rodzaje kluczy
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();
}
Zamiast tego należy użyć standardowego identyfikatora UUID V1? – ShadowChaser
Nie jestem pewien, czy jest to całkowicie poprawne - patrząc na implementację, jasne jest, że informacje o wersji/wariancie nie są przechowywane w najbardziej znaczących bitach, ale raczej gdzieś pośrodku. – Tom
@RasmusFaber Komentarz [Tom] (http://stackoverflow.com/users/223201/tom) jest poprawny: Odpowiedź tutaj jest ** niepoprawna o sześciu najbardziej znaczących bitach ** będących informacją o typie. Istnieje rzeczywiście sześć bitów danych nielosowych, ale cztery bity identyfikują wersję 4, a dwa inne są zarezerwowane.Cztery i dwa bity znajdują się w różnych pozycjach w pobliżu środka 128-bitowej wartości. Zobacz [artykuł Wikipedii] (https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_.28random.29). –
Dzięki @Tom and Basil. Zaktualizowałem odpowiedź. –