Когда следует использовать uuid.uuid1() vs. uuid.uuid4() в python?

Я понимаю различия между ними docs.

uuid1():
Создайте UUID из идентификатора хоста, порядкового номера и текущего времени

uuid4():
Создайте случайный UUID.

Итак, uuid1 использует информацию о машине/последовательности/времени для создания UUID. Каковы преимущества и недостатки использования каждого из них?

Я знаю, что uuid1() может иметь проблемы конфиденциальности, поскольку он основан на машинной информации. Интересно, есть ли более тонкие при выборе того или другого. Я просто использую uuid4() прямо сейчас, так как это полностью случайный UUID. Но мне интересно, следует ли использовать uuid1 для уменьшения риска столкновений.

В принципе, я ищу советы для лучших практик использования одного и другого. Спасибо!

Ответ 1

uuid1() гарантированно не приведет к каким-либо столкновениям (при условии, что вы не создадите слишком много из них одновременно). Я бы не использовал его, если важно, чтобы между uuid и компьютером не было никакой связи, так как MAC-адрес используется, чтобы сделать его уникальным на всех компьютерах.

Вы можете создавать дубликаты, создавая более 2 14 uuid1 менее чем за 100 нс, но это не проблема для большинства случаев использования.

uuid4() генерирует, как вы сказали, случайный UUID. Вероятность столкновения действительно, действительно, очень маленькая. Достаточно мало, чтобы вы не беспокоились об этом. Проблема состоит в том, что у плохого генератора случайных чисел вероятность того, что он столкнется с большей вероятностью.

Этот отличный ответ Боба Амана подводит итог. (Я рекомендую прочитать весь ответ.)

Откровенно говоря, в одном прикладном пространстве без злых актеров, исчезновение всей жизни на земле происходят задолго до того, столкновение, даже на версии 4 UUID, даже если вы создаете немало UUID в секунду.

Ответ 2

Один пример, когда вы можете считать uuid1(), а не uuid4() , когда UUID создаются на отдельных машинах, например, когда несколько онлайн-транзакций обрабатываются несколькими машинами для масштабирования.

В такой ситуации риск столкновения из-за неправильного выбора способа генерации генераторов псевдослучайных чисел, например, а также потенциально более высокое число выпущенных UUID, скорее всего, создает возможность создания дубликатов идентификаторов.

Другой интерес uuid1(), в этом случае заключается в том, что машина, в которой каждый GUID была первоначально создана, неявно записана (в разделе "node" UUID). Это и информация о времени, может помочь, если только при отладке.

Ответ 3

Моя команда столкнулась с трудностями при использовании UUID1 для обновления базы данных script, где мы создали ~ 120 тыс. UUID в течение нескольких минут. Столкновение UUID привело к нарушению ограничения первичного ключа.

Мы обновили 100 серверов, но в наших экземплярах Amazon EC2 мы столкнулись с этой проблемой несколько раз. Я подозреваю, что это плохое разрешение часов и переключение на UUID4 решило его для нас.

Ответ 4

Следует отметить, что при использовании uuid1, если вы используете вызов по умолчанию (не указав параметр clock_seq), у вас есть вероятность столкнуться с конфликтами: у вас есть только 14 бит случайности (генерация 18 записей в пределах 100 нс дает вы примерно на 1% вероятности столкновения см. парадокс/атаку дня рождения). Проблема не будет возникать в большинстве случаев использования, но на виртуальной машине с плохим разрешением часов она вас укусит.

Ответ 5

Возможно, что-то, о чем не упоминалось, относится к местности.

MAC-адрес или упорядочение по времени (UUID1) могут позволить увеличить производительность базы данных, поскольку она меньше работает для сортировки чисел поближе, чем распределенные случайным образом (UUID4) (см. здесь).

Вторая связанная с этим проблема заключается в том, что использование UUID1 может быть полезно при отладке, даже если исходные данные теряются или явно не хранятся (это, очевидно, противоречит проблеме конфиденциальности, упомянутой OP).

Ответ 6

В дополнение к принятому ответу есть третий вариант, который может быть полезен в некоторых случаях:

v1 со случайным MAC ( "v1mc" )

Вы можете сделать гибрид между v1 и v4, преднамеренно генерируя v1 UUID со случайным MAC-адресом широковещательной передачи (это разрешено спецификацией v1). В результате UUID v1 зависит от времени (например, обычный v1), но не имеет всей информации о конкретном хосте (например, v4). Он также намного ближе к v4 в нем: сопротивление столкновения: v1mc = 60 бит времени + 61 случайных бит = 121 уникальных бит; v4 = 122 случайных бита.

Первое место, с которым я столкнулся, это функция Postgres uuid_generate_v1mc(). С тех пор я использовал следующий эквивалент 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)

(примечание: у меня есть более длинная + более быстрая версия, которая напрямую создает объект UUID, может публиковать сообщения, если кто-то хочет)


В случае БОЛЬШИХ объемов вызовов/секунды, это может вывести системную случайность. Вместо этого вы можете использовать модуль stdlib random (вероятно, он будет быстрее). Но БУДЬТЕ ПРЕДОСТЕРЕЖЕННО: требуется только несколько сотен UUID, прежде чем злоумышленник сможет определить состояние RNG и, таким образом, частично предсказать будущие UUID.

import random
from uuid import uuid1

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