Создание глобально уникального идентификатора в Java

Резюме: Я разрабатываю постоянное веб-приложение Java, и мне нужно убедиться, что все оставшиеся ресурсы имеют глобально уникальные идентификаторы для предотвращения дублирования.

Тонкая печать:

  • Я не использую RDBMS, поэтому у меня нет генераторов воображаемой последовательности (например, Oracle)
  • Мне бы хотелось, чтобы это было быстро, желательно все в памяти - мне бы не пришлось открывать файл и увеличивать значение
  • Он должен быть потокобезопасным (я ожидаю, что только один JVM за один раз должен будет генерировать идентификаторы)
  • Должна быть согласованность между экземплярами JVM. Если сервер выключится и запустится, генератор ID не должен повторно генерировать те же идентификаторы, которые он сгенерировал в предыдущих экземплярах (или, по крайней мере, шанс должен быть действительно, очень тонким - я ожидаю много миллионов ресурсов)
  • Я видел примеры в EJB уникальной статье шаблона ID. Они не будут работать для меня (я бы предпочел не полагаться исключительно на System.currentTimeMillis(), потому что мы будем хранить несколько ресурсов за миллисекунду).
  • Я рассмотрел ответы, предложенные в этом вопросе. Моя забота о них такова, какова вероятность того, что я получу дубликат ID с течением времени? Меня заинтриговало предложение использовать java.util.UUID для UUID, но опять же, вероятность дублирования должна быть бесконечно малой.
  • Я использую JDK6

Ответ 1

Довольно уверены, что UUID "достаточно хороши". Имеются 340 282 366 920 938 463 463 374 607 431 770 000 000 UUID.

http://www.wilybeagle.com/guid_store/guid_explain.htm

"Чтобы представить эти цифры в перспективе, один ежегодный риск попадания метеорита оценивается как один шанс в 17 миллиардов, то есть вероятность составляет около 0,00000000006 (6 × 10-11), что эквивалентно шансам создавая несколько десятков триллионов UUID в год и имея один дубликат. Другими словами, только после генерации 1 миллиарда UUID каждую секунду в течение следующих 100 лет вероятность создания всего одного дубликата будет составлять около 50%. один дубликат будет составлять около 50%, если каждый человек на земле владеет 600 миллионами UUID"

http://en.wikipedia.org/wiki/Universally_Unique_Identifier

Ответ 2

Если для ПК необходимо быть уникальным: вы могли бы использовать (System.currentTimeMillis() << 4) | (staticCounter++ & 15) или что-то в этом роде.

Это позволит вам генерировать 16 в мс. Если вам нужно больше, сдвиньте на 5, а затем с 31...

если он должен быть уникальным на нескольких ПК, вы также должны объединить свой MAC-адрес основной сетевой карты.

изменить: уточнить

private static int staticCounter=0;
private final int nBits=4;
public long getUnique() {
    return (currentTimeMillis() << nBits) | (staticCounter++ & 2^nBits-1);
}

и измените nBits на квадратный корень из наибольшего числа, которое вам нужно создать за мс.

В конце концов он перевернется. Вероятно, 20 лет или что-то с nBits в 4.

Ответ 3

public class UniqueID {
    private static long startTime = System.currentTimeMillis();
    private static long id;

    public static synchronized String getUniqueID() {
        return "id." + startTime + "." + id++;
    }
}

Ответ 4

Из памяти удаленные пакеты RMI содержат генератор UUID. Я не знаю, стоит ли смотреть на это.

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

Он работает очень хорошо и невероятно быстро (как только вы впервые инициализировали MessageDigest).

Ответ 5

почему бы не сделать это

String id = Long.toString(System.currentTimeMillis()) + 
    (new Random()).nextInt(1000) + 
    (new Random()).nextInt(1000);

Ответ 6

если вы хотите использовать более короткую и быструю реализацию, которую java UUID взглянет на:

https://code.google.com/p/spf4j/source/browse/trunk/spf4j-core/src/main/java/org/spf4j/concurrent/UIDGenerator.java

см. варианты реализации и ограничения в javadoc.

здесь unit test о том, как использовать:

https://code.google.com/p/spf4j/source/browse/trunk/spf4j-core/src/test/java/org/spf4j/concurrent/UIDGeneratorTest.java