UUID
128-битный UUID был изобретен именно для вашей цели: Генерация идентификаторов на одной или нескольких машинах без координации через центральный орган.
В идеале вы должны использовать исходный UUID версии 1 или его варианты в версиях 2, 3 и 5. Оригинал берет MAC-адрес сетевого интерфейса хост-компьютера и объединяет его с текущим моментом плюс небольшое произвольное число, которое увеличивается, когда часы хоста настроены. Такой подход устраняет любые практические проблемы для дубликатов.
Java не связывает реализацию для генерации этих версий. Я предполагаю, что у разработчиков Java были проблемы с конфиденциальностью и безопасностью, касающиеся разглашения места, времени и MAC-адреса.
Java поставляется только с одной реализацией генератора для версии 4. В этом типе все, кроме 6, из 128 битов генерируются случайным образом. Если используется криптографически сильный генератор случайных чисел, эта версия достаточно хороша для использования в большинстве распространенных ситуаций, не заботясь о столкновениях.
Поймите, что 122 бита - это действительно большой диапазон чисел (5.316911983139664e + 36). 64-битные значения дают диапазон 18 446 744 073 709 552 000 (18 квинтиллионов). Остальные 58 бит (122-64 = 58) дают диапазон чисел 288,230,376,151,711,740 (288 квадриллионов). Теперь умножьте эти два числа, чтобы получить диапазон 122-бит: 2 ^ 122 = (18,446,744,073,709,552,000 * 288,230,376,151,711,740), что составляет 5,3 ундециллион .
Тем не менее, если у вас есть доступ к генерации версии UUID, отличной от 4, используйте ее. Например, в системе базы данных, такой как Postgres , сервер базы данных может генерировать номера UUID в различных версиях, включая версию 1. Или вы можете найти библиотеку Java для генерации таких UUID, хотя эта библиотека может не быть платформой -независимый (он может иметь собственный код внутри).
System.nanoTime
Имейте в виду, что System.nanoTime
не имеет ничего , имеющего отношение к текущей дате и времени. Процитирую Javadoc:
Этот метод может использоваться только для измерения прошедшего времени и не связан с каким-либо другим понятием системного или настенного времени.
Функция System.nanoTime
просто возвращает число long
, число наносекунд с некоторого происхождения, но это происхождение , а не , указанное .
Единственное обещание, данное в спецификации Java, заключается в том, что источник не изменится во время выполнения JVM. Таким образом, вы знаете, что число постоянно увеличивается во время выполнения вашего приложения. Если не достигнуто ограничение в long
, когда счетчик будет опрокидываться. Этот ролловер может занять 292 года (2 ^ 63 наносекунды), если источник равен нулю, но, опять же, источник не указан.
По моему опыту работы с конкретными реализациями Java, которые я использовал, источником является момент запуска JVM. Это означает, что я наверняка увижу одни и те же цифры снова и снова после следующего перезапуска JVM.
Так что использование System.nanoTime
в качестве идентификатора - плохой выбор. Если ваше приложение случайно совпадет с тем же самым наносекундным числом, как и в предыдущем запуске, это чистый шанс, но шанс, который вам не нужно использовать. Вместо этого используйте UUID.