web-dev-qa-db-fra.com

Probabilité de collision en utilisant les bits les plus significatifs d'un UUID dans Java

Si j'utilise Long uuid = UUID.randomUUID().getMostSignificantBits() quelle est la probabilité d'une collision? Il supprime les bits les moins significatifs, il est donc possible que vous vous heurtiez à une collision, non?

231
dlinsin

Selon la documentation , la méthode statique UUID.randomUUID() génère un UUID de type 4.

Cela signifie que six bits sont utilisés pour certaines informations de type et que les 122 bits restants sont attribués de manière aléatoire.

Les six bits non aléatoires sont distribués avec quatre dans la moitié la plus significative de l'UUID et deux dans la moitié la moins significative. Ainsi, la moitié la plus significative de votre UUID contient 60 bits de valeur aléatoire, ce qui signifie que vous devez en moyenne générer 2 ^ 30 UUID pour obtenir une collision (comparé à 2 ^ 61 pour le UUID complet).

Je dirais donc que vous êtes plutôt en sécurité. Notez cependant que cela n’est absolument pas vrai pour d’autres types d’UUID, comme le mentionne Carl Seleborg.

Incidemment, il serait légèrement préférable d’utiliser la moitié la moins significative de l’UUID (ou de simplement générer une valeur longue de manière aléatoire avec SecureRandom).

211
Rasmus Faber

Raymond Chen a un très bon billet de blog à ce sujet:

les GUID sont globalement uniques, mais les sous-chaînes de GUID ne le sont pas

55
Carl Seleborg

Je pense que c'est le meilleur exemple d'utilisation de randomUUID:

http://www.javapractices.com/topic/TopicAction.do?Id=56

13
Kannika

Vous feriez mieux de simplement générer une valeur longue aléatoire, alors tous les bits sont aléatoires. Dans Java 6, new Random () utilise System.nanoTime () plus un compteur en tant que graine.

Il existe différents niveaux d'unicité.

Si vous avez besoin d'unicité sur plusieurs machines, vous pouvez avoir une table de base de données centrale pour allouer des identifiants uniques, voire des lots d'identifiants uniques.

Si vous avez juste besoin d'unicité dans une application, vous pouvez simplement avoir un compteur (ou un compteur qui commence par currentTimeMillis () * 1000 ou nanoTime () en fonction de vos besoins).

10
Peter Lawrey

Utilisez Time YYYYDDDD (Année + Jour de l’Année) comme préfixe. Cela réduit la fragmentation de la base de données dans les tables et les index. Cette méthode retourne byte[40]. Je l'ai utilisé dans un environnement hybride où le SID Active Directory (varbinary(85)) est la clé pour les utilisateurs LDAP et un ID généré automatiquement par l'application est utilisé pour les utilisateurs non-LDAP. De plus, le grand nombre de transactions par jour dans les tables transactionnelles (secteur bancaire) ne peut pas utiliser les types standard Int pour les clés.

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