Probabilità di collisione utilizzando i bit più significativi di un UUID in Java


235

Se sto usando Long uuid = UUID.randomUUID().getMostSignificantBits()quanto è probabile che si verifichi una collisione. Taglia i bit meno significativi, quindi c'è la possibilità di incorrere in una collisione, giusto?

Risposte:


213

Secondo la documentazione , il metodo statico UUID.randomUUID()genera un UUID di tipo 4.

Ciò significa che vengono utilizzati sei bit per alcune informazioni di tipo e i rimanenti 122 bit vengono assegnati in modo casuale.

I sei bit non casuali sono distribuiti con quattro nella metà più significativa dell'UUID e due nella metà meno significativa. Quindi la metà più significativa dell'UUID contiene 60 bit di casualità, il che significa che in media è necessario generare 2 ^ 30 UUID per ottenere una collisione (rispetto a 2 ^ 61 per l'intero UUID).

Quindi direi che sei piuttosto al sicuro. Si noti, tuttavia, che ciò non è assolutamente vero per altri tipi di UUID, come menziona Carl Seleborg.

Per inciso, saresti leggermente meglio usando la metà meno significativa dell'UUID (o semplicemente generando un long casuale usando SecureRandom).


3
Non sono sicuro che sia del tutto corretto: guardando l'implementazione, è chiaro che le informazioni sulla versione / variante non sono memorizzate nei bit più significativi, ma piuttosto da qualche parte nel mezzo.
Tom,

2
@RasmusFaber Il commento di Tom è corretto: la risposta qui non è corretta in quanto i sei bit più significativi sono le informazioni sul tipo. Esistono effettivamente sei bit di dati non casuali, ma quattro bit identificano la versione 4 e altri due bit sono riservati. I quattro e due bit si trovano in posizioni diverse vicino al centro del valore di 128 bit. Vedi l' articolo di Wikipedia .
Basil Bourque,



10

Stai meglio solo generando un valore lungo casuale, quindi tutti i bit sono casuali. In Java 6, new Random () utilizza System.nanoTime () più un contatore come seed.

Esistono diversi livelli di unicità.

Se è necessaria l'univocità su più macchine, è possibile disporre di una tabella di database centrale per l'allocazione di ID univoci o persino batch di ID univoci.

Se hai solo bisogno di avere unicità in un'app puoi semplicemente avere un contatore (o un contatore che inizia da currentTimeMillis () * 1000 o nanoTime () a seconda delle tue esigenze)


7

Utilizzare Time YYYYDDDD(Year + Day of Year) come prefisso. Ciò riduce la frammentazione del database in tabelle e indici. Questo metodo ritorna byte[40]. L'ho usato in un ambiente ibrido in cui il SID di Active Directory ( varbinary(85)) è la chiave per gli utenti LDAP e un ID generato automaticamente dall'applicazione viene utilizzato per utenti non LDAP. Inoltre, il gran numero di transazioni al giorno nelle tabelle transazionali (settore bancario) non può utilizzare Inttipi standard per le chiavi

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

3
Perché non utilizzare invece un UUID V1 standard?
ShadowChaser,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.