Как генерировать уникальные идентификаторы на кластере веб-серверов - PullRequest
3 голосов
/ 30 октября 2009

В следующем сценарии:

1 База данных 4 веб-сервера

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

Ответы [ 5 ]

15 голосов
/ 30 октября 2009

Использовать UUID (http://www.ietf.org/rfc/rfc4122.txt). Коллизии маловероятны, и их можно устранить, если они происходят, путем регенерации нового UUID, или их можно предотвратить путем объединения уникального идентификатора для каждого сервера (например, MAC-адреса) : -

StringBuilder sb = new StringBuilder(UUID.randomUUID());
InetAddress address = InetAddress.getLocalHost();
String uid = sb.append(NetworkInterface.getByInetAddress(address).getHardwareAddress());
3 голосов
/ 30 октября 2009

Вы можете использовать UUID:

import java.util.UUID;        

UUID uuid = UUID.randomUUID();
System.out.println(uuid.toString());
1 голос
/ 30 октября 2009

Я не уверен, почему автоинкремент или последовательность недопустимы. Вы хотите, чтобы внутренний идентификатор не был "угадываемым"? Что, это похоже на номер счета, и вы не хотите, чтобы кто-то мог угадать действительный номер счета?

Ну, ладно, кроме уже упомянутых UUID, на ум приходят две очевидные возможности.

  1. Используйте последовательность, затем сгенерируйте случайное число и создайте номер счета из комбинации двух, используя алгоритм так, чтобы два разных номера последовательности не могли дать одно и то же окончательное число. Например, простой алгоритм может быть следующим: взять следующий порядковый номер, умножить на 12345678, сгенерировать случайное число от 0 до 12345678-1 и сложить их вместе.

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

Если у вас есть какая-то схема, в которой в качестве идентификатора используется идентификатор сервера, я рекомендую вам не использовать этот идентификатор просто как число, хранящееся где-то в файле конфигурации. Сейчас я работаю над системой, в которой кому-то пришла в голову блестящая идея дать каждому серверу «идентификатор сервера», который встроен для записи идентификаторов, а идентификатор сервера - это небольшое целое число, которое присваивается вручную. Это не слишком сложно в производстве, где есть только 3 сервера. Но при разработке и тестировании, когда новые серверы постоянно включаются и выключаются, а тестовые конфигурационные файлы постоянно разбрасываются, администрирование становится проблемой. Я бы не стал использовать период идентификатора сервера, но если вы собираетесь его использовать, сделайте его автоматически назначенным каким-либо центральным сервером или извлеките его из IP-адреса или из-за чего-то более безопасного.

1 голос
/ 30 октября 2009

Какую систему БД вы используете? Приложение знает, какой сервер делает запрос? Вы позволяете БД определять ключ или устанавливаете его в коде?

Это может быть так же просто, как использовать автоинкремент с префиксом или 2-е поле, указывающее сервер, который запросил ключ.

1 голос
/ 30 октября 2009

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

...