Вероятность столкновения с использованием наиболее значимых бит UUID в Java

Если я использую Long uuid = UUID.randomUUID().getMostSignificantBits(), насколько вероятен конфликт. Он отсекает наименее значимые биты, так что есть вероятность, что вы столкнулись с столкновением, верно?

Ответ 1

В соответствии с документацией статический метод UUID.randomUUID() генерирует UUID типа 4.

Это означает, что шесть бит используются для информации определенного типа, а остальные 122 бит назначаются случайным образом.

Шесть неслучайных битов распределяются с четырьмя в самой значительной половине UUID и двумя в наименее значимой половине. Таким образом, самая значительная половина вашего UUID содержит 60 бит случайности, что означает, что вы в среднем должны генерировать 2 ^ 30 UUID для получения столкновения (по сравнению с 2 ^ 61 для полного UUID).

Итак, я бы сказал, что вы довольно безопасны. Обратите внимание, однако, что это абсолютно неверно для других типов UUID, как упоминает Карл Селеборг.

Кстати, вам будет немного лучше, используя наименее значимую половину UUID (или просто создавая случайный длинный с помощью SecureRandom).

Ответ 4

Вам лучше просто генерировать случайное длинное значение, тогда все биты будут случайными. В Java 6 новый Random() использует System.nanoTime() плюс счетчик в качестве семени.

Существуют разные уровни уникальности.

Если вам нужна уникальность на многих машинах, вы можете иметь центральную таблицу базы данных для выделения уникальных идентификаторов или даже партий уникальных идентификаторов.

Если вам просто нужно иметь уникальность в одном приложении, вы можете просто иметь счетчик (или счетчик, который начинается с currentTimeMillis() * 1000 или nanoTime() в зависимости от ваших требований)

Ответ 5

Использовать время YYYYDDDD (Год + День года) в качестве префикса. Это уменьшает фрагментацию базы данных в таблицах и индексах. Этот метод возвращает byte[40]. Я использовал его в гибридной среде, где SID Active Directory (varbinary(85)) является ключом для пользователей LDAP, и для пользователей, не являющихся LDAP, используется автоматически сгенерированный идентификатор приложения. Также большое количество транзакций в день в транзакционных таблицах (Банковская индустрия) не может использовать стандартные типы Int для ключей

private static final DecimalFormat timeFormat4 = new DecimalFormat("0000;0000");

public static byte[] getSidWithCalendar() {
    Calendar cal = Calendar.getInstance();
    String val = String.valueOf(cal.get(Calendar.YEAR));
    val += timeFormat4.format(cal.get(Calendar.DAY_OF_YEAR));
    val += UUID.randomUUID().toString().replaceAll("-", "");
    return val.getBytes();
}