Я знаю, что рандомизированные UUID имеют очень, очень, очень низкую вероятность коллизии в теории, но мне интересно на практике, насколько хороши Java с randomUUID()
точки зрения отсутствия коллизий? У кого-нибудь есть опыт, которым можно поделиться?
311
Ответы:
Использует UUID
java.security.SecureRandom
, который должен быть «криптографически сильным». Хотя фактическая реализация не указана и может варьироваться между JVM (это означает, что любые конкретные высказывания действительны только для одной конкретной JVM), она требует, чтобы выходные данные проходили статистический тест генератора случайных чисел.Реализация всегда может содержать скрытые ошибки, которые разрушают все это (см. Ошибка генерации ключа OpenSSH), но я не думаю, что есть какая-то конкретная причина для беспокойства по поводу случайности Java UUID.
источник
У Википедии очень хороший ответ http://en.wikipedia.org/wiki/Universally_unique_identifier#Collisions
источник
UUID.randomUUID()
, а не в теоретических шансах для данного идеального генератора случайных чисел.Существуют
2^122
возможные значения для UUID типа 4. (В спецификации сказано, что вы теряете 2 бита для типа и еще 4 бита для номера версии.)Предполагая, что вы должны были генерировать 1 миллион случайных UUID в секунду, шансы дублирования в вашей жизни были бы чрезвычайно малы. И чтобы обнаружить дубликаты, вам нужно решить задачу сравнения 1 миллиона новых UUID в секунду со всеми UUID, которые вы сгенерировали ранее 1 !
Вероятность того, что кто-либо испытал (то есть действительно заметил ) дубликат в реальной жизни, даже меньше, чем исчезающе мала ... из-за практической трудности поиска столкновений.
Теперь, конечно, вы обычно будете использовать генератор псевдослучайных чисел, а не источник действительно случайных чисел. Но я думаю, мы можем быть уверены, что если вы используете надежного провайдера для своих случайных чисел с криптографической стойкостью, то это будет криптографическая стойкость, и вероятность повторов будет такой же, как для идеального (не смещенного) генератора случайных чисел ,
Однако если вы используете JVM с «сломанным» генератором криптослучайных чисел, все ставки отключены. (И это может включать некоторые обходные пути для проблем «нехватки энтропии» в некоторых системах. Или вероятность того, что кто-то возился с вашей JRE, либо в вашей системе, либо в восходящем направлении.)
1 - Предполагая, что вы использовали «некое двоичное btree», как предложено анонимным комментатором, каждому UUID потребуются
O(NlogN)
биты оперативной памяти для представленияN
различных UUID, предполагающих низкую плотность и случайное распределение битов. Теперь умножьте это на 1 000 000 и количество секунд, для которых вы собираетесь запустить эксперимент. Я не думаю, что это практично в течение периода времени, необходимого для проверки на столкновения высококачественного ГСЧ. Даже с (гипотетическими) умными представлениями.источник
Я не эксперт, но я бы предположил, что достаточно умные люди смотрели на генератор случайных чисел Java на протяжении многих лет. Следовательно, я бы также предположил, что случайные UUID хороши. Таким образом, у вас должна быть теоретическая вероятность коллизии (которая составляет около 1: 3 × 10 ^ 38 для всех возможных UUID. Кто-нибудь знает, как это меняется только для случайных UUID? Это
1/(16*4)
из вышеперечисленного?)Из моего практического опыта я никогда не видел каких-либо столкновений. Я, наверное, отрасту удивительно длинную бороду в день, когда получу свою первую;)
источник
У бывшего работодателя у нас была уникальная колонка, в которой содержался случайный uuid. Мы получили столкновение в первую неделю после его развертывания. Конечно, шансы низкие, но они не равны нулю. Вот почему Log4j 2 содержит UuidUtil.getTimeBasedUuid. Он будет генерировать UUID, который является уникальным в течение 8 925 лет, при условии, что вы не генерируете более 10 000 UUID / миллисекунду на одном сервере.
источник
Первоначальная схема генерации UUID состояла в том, чтобы объединить версию UUID с MAC-адресом компьютера, который генерирует UUID, и с числом интервалов в 100 наносекунд с момента принятия григорианского календаря на Западе. Представляя одну точку в пространстве (компьютер) и время (количество интервалов), вероятность столкновения значений практически равна нулю.
источник
Во многих ответах обсуждается, сколько UUID должно быть сгенерировано, чтобы достичь 50% вероятности коллизии. Но вероятность столкновения 50%, 25% или даже 1% бесполезна для приложения, где столкновение должно быть (практически) невозможно.
Программисты обычно отклоняют как «невозможные» другие события, которые могут и происходят?
Когда мы записываем данные на диск или в память и снова читаем их, мы считаем само собой разумеющимся, что данные верны. Мы полагаемся на исправление ошибок устройства, чтобы обнаружить любое повреждение. Но вероятность необнаруженных ошибок на самом деле составляет около 2 -50 .
Разве не имеет смысла применять подобный стандарт к случайным UUID? Если вы это сделаете, вы обнаружите, что «невозможное» столкновение возможно в наборе около 100 миллиардов случайных UUID (2 36,5 ).
Это астрономическое число, но такие приложения, как поэлементное выставление счетов в национальной системе здравоохранения или регистрация данных высокочастотного датчика на большом множестве устройств, могут определенно выйти за эти пределы. Если вы пишете следующее Руководство автостопом по Галактике, не пытайтесь назначать UUID для каждой статьи!
источник
Так как большинство ответов были сосредоточены на теории, я думаю, что могу что-то добавить к обсуждению, дав практический тест, который я сделал. В моей базе данных около 4,5 миллионов UUID, сгенерированных с помощью Java 8 UUID.randomUUID (). Следующие из них - только некоторые, которые я узнал:
c0f55f62 -b990-47bc-8caa-f42313669948
c0f55f62 -e81e-4253-8299-00b4322829d5
c0f55f62 -4979-4e87-8cd9-1c556894e2bb
b9ea2498-fb32-40ef-91ef-0ba 00060fe64
be87a209-2114-45b3-9d5a-86d 00060fe64
4a8a74a6-e972-4069-b480-b dea1177b21f
12fb4958-bee2-4c89-8cf8-e dea1177b21f
Если бы это было действительно случайно, вероятность наличия подобных идентификаторов UUID была бы значительно ниже (см. Редактирование), поскольку мы рассматриваем только 4,5 миллиона записей. Так что, хотя эта функция хороша, с точки зрения отсутствия коллизий, для меня она не кажется такой хорошей, как это было бы в теории.
Редактировать :
Многие люди, похоже, не понимают этого ответа, поэтому я проясню свою точку зрения: я знаю, что сходство «мало» и далеко не полное столкновение. Однако я просто хотел сравнить UUID.randomUUID () в Java с генератором истинных случайных чисел, что является актуальным вопросом.
В истинном генераторе случайных чисел вероятность возникновения последнего случая будет около = 0,007%. Поэтому я думаю, что мой вывод верен.
Формула объясняется в этой статье вики en.wikipedia.org/wiki/Birthday_problem
источник
Я играю в лотерею в прошлом году, и я никогда не выигрывал .... но похоже, что в лотерее есть победители ...
документ: http://tools.ietf.org/html/rfc4122
Тип 1: не реализовано. Столкновение возможно, если UUID генерируется в тот же момент. impl может быть искусственно синхронизирован, чтобы обойти эту проблему.
Тип 2: никогда не видеть реализацию.
Тип 3: хэш md5: возможна коллизия (128 бит-2 технических байтов)
Тип 4: случайный: возможно столкновение (как лотерея). обратите внимание, что в jdk6 не используется «истинное» безопасное случайное число, поскольку разработчик не выбирает алгоритм PRNG, и вы можете заставить систему использовать «плохой» алгоритм PRNG. Так что ваш UUID предсказуем.
Тип 5: хэш sha1: не реализовано: возможно столкновение (160 бит-2 технических байтов)
источник
Мы использовали случайный UUID Java в нашем приложении более одного года, и это очень широко. Но мы никогда не сталкиваемся с столкновением.
источник