¿Cuándo debo usar uuid.uuid1() frente a uuid.uuid4() en python?

7 minutos de lectura

avatar de usuario
cohetes

Entiendo las diferencias entre los dos de la documentos

uuid1():
Genere un UUID a partir de un ID de host, un número de secuencia y la hora actual

uuid4():
Genera un UUID aleatorio.

Asi que uuid1 utiliza información de máquina/secuencia/tiempo para generar un UUID. ¿Cuáles son los pros y los contras de usar cada uno?

lo sé 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 a la hora de elegir uno u otro. solo uso uuid4() ahora mismo, ya que es un UUID completamente aleatorio. Pero me pregunto si debería estar usando uuid1 para disminuir el riesgo de colisiones.

Básicamente, estoy buscando los consejos de las personas sobre las mejores prácticas para usar uno frente al otro. ¡Gracias!

  • Aquí hay un enfoque alternativo a UUID. Aunque la posibilidad de colisión es infinitesimal, el UUID no garantiza la unicidad. Para garantizar la unicidad, es posible que desee utilizar la clave compuesta como [<system id>,<local id>]. Cada sistema que participa en el intercambio de datos debe tener su propia identificación única del sistema, ya sea asignada durante la configuración del sistema u obtenida de un grupo común de identificaciones. La identificación local es una identificación única dentro de cualquier sistema en particular. Esto implica más molestias pero garantiza la singularidad. Perdón por el offtopic, solo intento ayudar.

    – oᴉɹǝɥɔ

    27 de marzo de 2013 a las 14:55

  • No se ocupa de las “preocupaciones de privacidad” que mencionó

    – Shrey

    4 de agosto de 2014 a las 10:27

avatar de usuario
Georg Scholly

uuid1() está garantizado que no producirá ninguna colisión (suponiendo que no cree demasiadas al mismo tiempo). No lo usaría si es importante que no haya conexión entre el uuid y la computadora, ya que la dirección mac se usa para que sea única en todas las computadoras.

Puede crear duplicados creando más de 214 uuid1 en menos de 100 ns, 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 realmente, realmente, De Verdad pequeña. Lo suficientemente pequeño como para que no debas preocuparte por eso. El problema es que un mal generador de números aleatorios hace que sea más probable que haya colisiones.

Esta excelente respuesta de Bob Aman lo resume muy bien. (Recomiendo leer la respuesta completa).

Francamente, en un solo espacio de aplicación sin actores maliciosos, la extinción de toda la vida en la tierra ocurrirá mucho antes de que ocurra una colisión, incluso en un UUID de la versión 4, incluso si está generando bastantes UUID por segundo.

  • Lo siento, comenté sin investigar completamente: hay bits reservados para evitar que un uuid de la versión 4 colisione con un uuid de la versión 1. Eliminaré mi comentario original. Ver tools.ietf.org/html/rfc4122

    – Mark Ransom

    23 de noviembre de 2009 a las 22:50

  • @gs Sí, tiene sentido con lo que estaba leyendo. uuid1 es “más exclusivo”, mientras que uuid4 es más anónimo. Entonces, básicamente, use uuid1 a menos que tenga una razón para no hacerlo. @mark ransom: Excelente respuesta, no apareció cuando busqué uuid1/uuid4. Directamente de la boca del caballo, parece.

    – monos cohete

    25 de noviembre de 2009 a las 17:22

  • uuid1 no producirá necesariamente UUID únicos si produce varios por segundo en el mismo nodo. Ejemplo: [uuid.uuid1() for i in range(2)]. A menos, por supuesto, que esté pasando algo extraño que me esté perdiendo.

    – Michael Mior

    16 de noviembre de 2013 a las 4:14


  • @Miguel: 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.

    – Georg Scholly

    17 de noviembre de 2013 a las 19:56

  • @Michael: Intenté investigar las circunstancias en las que ocurren las colisiones y agregué la información que encontré.

    – Georg Scholly

    18 de noviembre de 2013 a las 18:06

avatar de usuario
mjv

Una instancia en la que puede considerar uuid1() más bien que uuid4() es cuando los UUID se producen en máquinas separadaspor ejemplo, cuando se procesan múltiples transacciones en línea en varias máquinas con fines de escalado.

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, por ejemplo, y también los números potencialmente más altos de UUID producidos hacen más probable la posibilidad de crear ID duplicados.

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). Esto y la información de tiempo pueden ayudar, aunque solo sea con la depuración.

Mi equipo acaba de tener problemas para usar UUID1 para un script de actualización de base de datos en el que generamos ~120k UUID en un par de minutos. La colisión de UUID condujo a la violación de una restricción de clave principal.

Hemos actualizado cientos de servidores, pero en nuestras instancias de Amazon EC2 nos encontramos con este problema varias veces. Sospecho que la mala resolución del reloj y el cambio a UUID4 lo solucionaron.

Una cosa a tener en cuenta al usar uuid1si usa la llamada predeterminada (sin dar clock_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 colisión, vea la paradoja/ataque de cumpleaños). 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 deficiente, lo morderá.

Quizás algo que no se ha mencionado es el de la localidad.

Una dirección MAC o una ordenación basada en el tiempo (UUID1) puede permitir un mayor rendimiento de la base de datos, ya que es menos trabajo ordenar números más juntos que los distribuidos aleatoriamente (UUID4) (ver aquí).

Un segundo problema relacionado es que el uso de 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).

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 colisiones: v1mc = 60 bits de tiempo + 61 bits aleatorios = 121 bits únicos; v4 = 122 bits aleatorios.

El primer lugar donde encontré esto fue Postgres’ uuid_generate_v1mc() función. Desde entonces, he usado el siguiente equivalente de Python:

from os import urandom
from uuid import uuid1
_int_from_bytes = int.from_bytes  # py3 only

def uuid1mc():
    # NOTE: The constant here is required by the UUIDv1 spec...
    return uuid1(_int_from_bytes(urandom(6), "big") | 0x010000000000)

(nota: tengo una versión más larga y más rápida que crea el objeto UUID directamente; puede publicar si alguien quiere)


En caso de GRANDES volúmenes de llamadas/segundo, esto tiene el potencial de agotar la aleatoriedad del sistema. Tú pudo usar la biblioteca estándar random módulo en su lugar (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 del RNG y, por lo tanto, predecir parcialmente los UUID futuros.

import random
from uuid import uuid1

def uuid1mc_insecure():
    return uuid1(random.getrandbits(48) | 0x010000000000)

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad