Генерация глобального уникального идентификатора в Java

StackOverflow https://stackoverflow.com/questions/192920

Вопрос

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

Мелкий шрифт .

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

    Решение

    Довольно уверены, что 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 & # 215; 10 & # 8722; 11), что эквивалентно вероятности создания нескольких десятков триллионов UUID в год и наличия одного дубликата. Другими словами, только после генерирования 1 миллиарда UUID каждую секунду в течение следующих 100 лет вероятность создания только одного дубликата составит около 50%. Вероятность появления одного дубликата составит около 50%, если каждый человек на земле будет владеть 600 миллионами UUID & "

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

    Другие советы

    public class UniqueID {
        private static long startTime = System.currentTimeMillis();
        private static long id;
    
        public static synchronized String getUniqueID() {
            return "id." + startTime + "." + id++;
        }
    }
    

    Если он должен быть уникальным для каждого ПК: вы можете использовать (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.

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

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

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

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

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

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

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

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

    Вот модульный тест по использованию:

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

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top