Entiendo las diferencias entre los dos de los documentos.
uuid1()
:
Generar un UUID a partir de una ID de host, un número de secuencia y la hora actual
uuid4()
:
Genera un UUID aleatorio.
Entonces uuid1
usa información de máquina / secuencia / tiempo para generar un UUID. ¿Cuáles son los pros y los contras de usar cada uno?
Sé que uuid1()
puede tener problemas de privacidad, ya que se basa en la información de la máquina. Me pregunto si hay algo más sutil al elegir uno u otro. Solo lo uso en uuid4()
este momento, ya que es un UUID completamente aleatorio. Pero me pregunto si debería usarlo uuid1
para disminuir el riesgo de colisiones.
Básicamente, estoy buscando consejos de las personas para las mejores prácticas sobre el uso de uno frente al otro. ¡Gracias!
Respuestas:
uuid1()
está garantizado para no producir colisiones (bajo el supuesto de que no crea demasiadas al mismo tiempo). No lo usaría si es importante que no haya conexión entreuuid
la computadora y la computadora, ya que la dirección MAC se utiliza para que sea única en todas las computadoras.Puede crear duplicados creando más de 2 14 uuid1 en menos de 100ns, pero esto no es un problema para la mayoría de los casos de uso.
uuid4()
genera, como dijiste, un UUID aleatorio. La posibilidad de una colisión es muy, muy, muy pequeña. Lo suficientemente pequeño como para no preocuparse por eso. El problema es que un mal generador de números aleatorios hace que sea más probable que tenga colisiones.Esta excelente respuesta de Bob Aman lo resume muy bien. (Recomiendo leer la respuesta completa).
fuente
uuid1
no necesariamente producirá UUID únicos si produce varios por segundo en el mismo nodo. Ejemplo:[uuid.uuid1() for i in range(2)]
. A menos que, por supuesto, ocurra algo extraño que me estoy perdiendo.uuid1
tiene un número de secuencia (cuarto elemento en su ejemplo), por lo que, a menos que use todos los bits en el contador, no tiene ninguna colisión.Una instancia en la que puede considerar en
uuid1()
lugar de hacerlouuid4()
es cuando los UUID se producen en máquinas separadas , por ejemplo, cuando se procesan varias transacciones en línea en varias máquinas con fines de escala.En tal situación, los riesgos de tener colisiones debido a malas elecciones en la forma en que se inicializan los generadores de números pseudoaleatorios, y también los números potencialmente más altos de UUID producidos hacen más probable la posibilidad de crear ID duplicadas.
Otro interés de
uuid1()
, en ese caso, es que la máquina donde se produjo inicialmente cada GUID se registra implícitamente (en la parte "nodo" de UUID). Esta y la información de tiempo pueden ayudar aunque solo sea con la depuración.fuente
Mi equipo acaba de tener problemas al usar UUID1 para un script de actualización de base de datos donde generamos ~ 120k UUID en un par de minutos. La colisión UUID condujo a la violación de una restricción de clave primaria.
Hemos actualizado cientos de servidores, pero en nuestras instancias de Amazon EC2 nos encontramos con este problema varias veces. Sospecho que la baja resolución del reloj y el cambio a UUID4 lo resolvieron por nosotros.
fuente
Una cosa a tener en cuenta al usar
uuid1
, si usa la llamada predeterminada (sin darclock_seq
parámetro), tiene la posibilidad de encontrarse con colisiones: tiene solo 14 bits de aleatoriedad (generar 18 entradas dentro de 100ns le da aproximadamente un 1% de probabilidad de una colisión. cumpleaños paradoja / ataque). El problema nunca ocurrirá en la mayoría de los casos de uso, pero en una máquina virtual con una resolución de reloj pobre, lo morderá.fuente
clock_seq
....Quizás algo que no se ha mencionado es el de la localidad.
Una dirección MAC o un pedido basado en el tiempo (UUID1) puede permitir un mayor rendimiento de la base de datos, ya que es menos difícil ordenar los números de forma más cercana que los distribuidos aleatoriamente (UUID4) (ver aquí ).
Un segundo problema relacionado es que usar UUID1 puede ser útil en la depuración, incluso si los datos de origen se pierden o no se almacenan explícitamente (esto obviamente está en conflicto con el problema de privacidad mencionado por el OP).
fuente
Además de la respuesta aceptada, hay una tercera opción que puede ser útil en algunos casos:
v1 con MAC aleatorio ("v1mc")
Puede hacer un híbrido entre v1 y v4 generando deliberadamente UUID v1 con una dirección MAC de transmisión aleatoria (esto está permitido por la especificación v1). El UUID v1 resultante depende del tiempo (como v1 normal), pero carece de toda la información específica del host (como v4). También está mucho más cerca de v4 en su resistencia a la colisión: v1mc = 60 bits de tiempo + 61 bits aleatorios = 121 bits únicos; v4 = 122 bits aleatorios.
El primer lugar donde encontré esto fue la función uuid_generate_v1mc () de Postgres . Desde entonces he usado el siguiente equivalente de Python:
(nota: tengo una versión más larga + más rápida que crea el objeto UUID directamente; puede publicar si alguien lo desea)
En el caso de GRANDES volúmenes de llamadas / segundo, esto tiene el potencial de agotar la aleatoriedad del sistema. En su lugar, podría usar el
random
módulo stdlib (probablemente también será más rápido). Pero tenga cuidado: solo se necesitan unos pocos cientos de UUID antes de que un atacante pueda determinar el estado de RNG y, por lo tanto, predecir parcialmente futuros UUID.fuente