Java: уникальный 10-значный идентификатор



Мне нужно сгенерировать уникальный 10-значный идентификатор в Java. Вот ограничения для этого идентификатора:




  • Только Числовые

  • максимум 10 цифр

  • возможно создание до 10 различных идентификаторов в секунду

  • должен быть уникальным (даже если приложение запускается повторно)

  • невозможно сохранить номер в базе данных

  • как можно быстрее, чтобы не добавить много латентности в систему


Лучшее решение, которое я нашел до сих пор, следующее:



private static int inc = 0;

private static long getId(){

long id = Long.parseLong(String.valueOf(System.currentTimeMillis())
.substring(1,10)
.concat(String.valueOf(inc)));
inc = (inc+1)%10;
return id;
}


Это решение имеет следующие проблемы:




  • Если по какой-либо причине необходимо создать более 10 идентификаторов в секунду, это решение не будет работать.

  • примерно через 32 года этот идентификатор может быть повторен (это, вероятно, приемлемо)


Любое другое решение для создания этого идентификатора?



Есть еще какие-нибудь проблемы, о которых я не подумал со своей?



Спасибо за помощь,

608   4  

4 ответов:

Это небольшое улучшение для вашего, но должно быть устойчивым.

private static final long LIMIT = 10000000000L;
private static long last = 0;

public static long getID() {
  // 10 digits.
  long id = System.currentTimeMillis() % LIMIT;
  if ( id <= last ) {
    id = (last + 1) % LIMIT;
  }
  return last = id;
}

Как оно должно управлять до 1000 в секунду с относительно короткой скоростью цикла. Чтобы увеличить скорость цикла (но сократить разрешение), можно использовать (System.currentTimeMillis() / 10) % 10000000000L или (System.currentTimeMillis() / 100) % 10000000000L.

Это может быть сумасшедшая идея, но это идея :).

  • Сначала генерируем UUID и получаем его строковое представление с помощью java.util.UUID.randomUUID().toString()
  • Второе преобразование сгенерированной строки в байтовый массив (byte[])

  • Затем преобразуйте его в длинный буфер: java.nio.ByteBuffer.wrap( byte digest[] ).asLongBuffer().get()

  • Усечь до 10 цифр

Не уверен в уникальности этого подхода tho, я знаю, что вы можете положиться на уникальность UUID, но не проверил, насколько уникальны они преобразованы и усечены до 10 цифры длинного номера.

Пример был взят из JavaRanch , может быть, есть еще.

Edit: поскольку вы ограничены 10 цифрами, возможно, Вам будет достаточно простого генератора случайных чисел, загляните в этот вопрос/ответы на SO: Java: случайное длинное число в диапазоне 0

Что означает, что он должен быть уникальным? Даже через более запущенные в данный момент экземпляры? Это ломает вашу реализацию.

Если он должен быть уникальным во всей Вселенной, лучшим решением является использование UUID, поскольку это математически доказанный генератор идентификаторов, поскольку он генерирует уникальное значение для каждой вселенной. Менее точное число приносит вам столкновения.

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

Private static AtomicReference currentTime = new AtomicReference (System.currentTimeMillis ());

public static Long nextId() {
    return currentTime.accumulateAndGet(System.currentTimeMillis(), (prev, next) -> next > prev ? next : prev + 1) % 10000000000L;
}

Comments

    Ничего не найдено.