Ну, если я отброшу тот факт, что считаю это плохой идеей, и сконцентрируюсь на решении вашей проблемы, вот что я бы сделал:
У вас есть диапазон идентификаторов 10 ^ 63, что соответствует примерно 60 битам. Вы хотите, чтобы он был «глобально» и «локально» уникальным. Давайте сгенерируем первые N битов, которые будут глобально уникальными, а остальные - локально уникальными. Объединение двух будет иметь свойства, которые вы ищете.
Во-первых, глобальная уникальность: IP не будет работать, особенно локальные, в них очень мало энтропии. Я бы пошел с MAC-адресами, они были созданы для того, чтобы быть глобально уникальными. Они охватывают диапазон 256 ^ 6, поэтому используются 6 * 8 = 48 бит.
Теперь для локально уникальных: почему бы не использовать идентификатор процесса? Я делаю предположение, что уникальность каждого процесса, если нет, вам придется думать о чем-то еще. В Linux идентификатор процесса составляет 32 бита. Если мы хотим придираться, 2 старших байта, вероятно, содержат очень мало энтропии, как это было бы в 0 на большинстве машин. Поэтому отбросьте их, если знаете, что делаете.
Итак, теперь вы увидите, что у вас есть проблема, так как она будет использовать до 70 бит для генерации приличного (но не пуленепробиваемого) глобального и локального уникального идентификатора (в любом случае, используя мою технику). И поскольку я бы также посоветовал ввести случайное число (длиной не менее 8 бит) на всякий случай, оно точно не подойдет. Поэтому на вашем месте я бы хэшировал ~ 78 сгенерированных битов в SHA1 (например) и конвертировал первые 60 бит результирующего хэша в ваш формат идентификатора. Для этого обратите внимание, что у вас есть выбор из 63 символов, то есть почти полный диапазон из 6 бит. Итак, разбейте хеш на 6 битных частей и используйте первые 10 частей, чтобы выбрать 10 символов вашего идентификатора из 63 символов. Очевидно, что диапазон из 6 битов равен 64 возможным значениям (вам нужно только 63), поэтому, если у вас есть 6-битная часть, равная 63, либо возведите ее в 62 или предположите по модулю 63 и выберите 0. Это слегка сместит распределение, но это не так уж плохо.
Итак, это должно дать вам приличный глобальный и локальный псевдо-уникальный идентификатор.
Несколько последних моментов: в соответствии с парадоксом дня рождения , вы получите ~ 1% вероятности столкновений после генерации ~ 142 миллионов идентификаторов и 99% после генерации 3 миллиардов идентификаторов. Поэтому, если вы добились большого коммерческого успеха и генерировали миллионы идентификаторов, получите больший идентификатор.
Наконец, я думаю, что предоставил решение вашей проблемы «лучше, чем хуже», но я не могу не думать, что вы атакуете эту проблему неправильно, и, возможно, как уже упоминали другие, неправильно читая спецификации , Так что используйте это, если нет других способов, которые были бы более «пуленепробиваемыми» (централизованный поставщик идентификаторов, гораздо более длинный идентификатор ...).
Редактировать: Я перечитал ваш вопрос, и вы говорите, что вызываете эту функцию, возможно, много раз в секунду. Я предполагал, что это должно было служить неким идентификатором приложения, сгенерированным один раз в начале вашего приложения, и никогда не изменявшимся до его выхода. Так как это не так, вы должны обязательно добавить случайное число, и если вы генерируете много идентификаторов, сделайте это как минимум 32-битным числом. И прочитайте и перечитайте Парадокс Дня Рождения, на который я ссылался выше. И запустите ваш генератор чисел в высоко энтропийное значение, например, в значение usec текущей временной метки. Или даже пойти так далеко, чтобы получить ваши случайные значения из / dev / urandom.
Честно говоря, мое мнение о том, что 60 бит, вероятно, недостаточно ...