Probabilité de Collision de L'ObjectId vs UUID dans un grand système distribué

considérant Qu'un UUID rfc 4122 (16 octets) est beaucoup plus grand qu'un MongoDB ObjectId (12 octets), j'essaie de voir comment leur probabilité de collision se compare.

je sais que c'est quelque chose autour de tout à fait rare, mais dans mon cas la plupart des ids seront générés dans un grand nombre de clients mobiles, pas dans un ensemble limité de serveurs. je me demande si dans ce cas, il y a lieu d'être préoccupé par.

<!-Par rapport au cas normal où tous les codes sont générés par un petit nombre de clients:

  • Il pourrait prendre des mois pour détecter une collision depuis la création du document
  • les identificateurs sont générés à partir d'une clientèle beaucoup plus importante
  • chaque client a un taux de génération D'ID plus faible
21
demandé sur SystematicFrank 2014-03-24 14:11:57

2 réponses

dans mon cas, la plupart des identifiants seront générés par un grand nombre de clients mobiles, et non par un ensemble limité de serveurs. Je me demande si, dans ce cas, il y a une préoccupation justifiée.

cela ressemble à une très mauvaise architecture pour moi. Utilisez-vous une architecture à deux niveaux? Pourquoi les clients mobiles auraient-ils un accès direct à la base de données? Voulez-vous vraiment compter sur la sécurité du réseau?

en tout cas, quelques réflexions sur la collision probabilité:

ni UUID ni ObjectId ne se fondent sur leur taille, c'est-à-dire que les deux ne sont pas des nombres aléatoires, mais ils suivent un schéma qui tente de réduire systématiquement la probabilité de collision. Dans le cas de objectifs, leur structure est:

  • 4 octets de secondes depuis l'époque unix
  • 3 octets identifiant de la machine
  • 2 octets id de processus
  • 3 octets compteur

cela signifie que, contrairement aux UUIDs, les objectifs sont monotone (sauf en une seconde), qui est probablement leur propriété la plus importante. Les index monotoniques feront que L'arbre B sera rempli plus efficacement, il permet la pagination par id et permet un 'tri par défaut' par id pour rendre vos curseurs stables, et bien sûr, ils portent une estampille temporelle facile à extraire. Ce sont les optimisations dont vous devez être conscient, et elles peuvent être énormes.

comme vous pouvez le voir à partir de la structure des 3 autres composants, les collisions deviennent très probables si vous êtes faire > 1K inserts / s sur un seul processus (pas vraiment possible, pas même à partir d'un serveur), ou si le nombre de machines dépasse environ 10 (voir problème d'anniversaire), ou si le nombre de processus sur une seule machine devient trop grand (encore une fois, ce ne sont pas des nombres aléatoires, mais ils sont vraiment uniques sur une machine, mais ils doivent être raccourcis à deux octets).

Naturellement, pour une collision se produise, ils doivent correspondre ces aspects, donc même si deux machines ont la même hachage machine, il faudrait quand même qu'un client insère avec la même valeur de compteur dans la même seconde exacte et le même id de processus, mais oui, ces valeurs pourraient entrer en collision.

24
répondu mnemosyn 2014-03-24 10:46:59

regardons la spécification pour "ObjectId" de la documentation:

vue d'ensemble

ObjectId est un type de BSON de 12 octets, construit en utilisant:

  • une valeur de 4 octets représentant le nombre de secondes depuis l'époque Unix,
  • 3 octets machine identificateur
  • 2 octets id de processus, et
  • un compteur de 3 octets, commençant par une valeur aléatoire.

Donc laisser nous considérons cela dans le contexte d'un "client mobile".

Remarque: Le contexte ici signifie utiliser une connexion "directe" du "client mobile" à la base de données. Que doit faire. Mais la génération "_id" être fait tout simplement.

Donc les points:

  1. valeur pour les "secondes depuis l'époque". Qui va être assez aléatoire par demande. Donc impact de collision minime juste sur ce composant. Bien qu'en"secondes".

  2. le"code d'identification de la machine". Donc, ce client générant le _id valeur. Ceci élimine la possibilité d'une nouvelle "collision".

  3. le "process id". Donc là où c'est accessible à seed ( et il devrait l'être ) alors le produit _id a plus chance d'éviter collision.

  4. La "valeur aléatoire". Donc un autre "client" a réussi à générer toutes les mêmes valeurs que ci-dessus et réussi à générer le valeur aléatoire.

L'essentiel est, si n'est pas un argument assez convaincant pour digérer, puis il suffit de fournir votre propre "uuid" entrées "clé primaire".

juste argument convaincant pour considérer que les aspects de collision ici sont très large. Pour dire le moins.

rubrique est probablement juste un peu "trop large". Mais j'espère que cela déplace la considération un peu plus loin de "tout à fait improbable" et sur quelque chose un peu plus concret.

11
répondu Neil Lunn 2014-03-24 10:44:18