Как генерировать уникальные целочисленные идентификаторы, такие как Facebook Twitter - PullRequest
18 голосов
/ 16 февраля 2012

После поиска на SO и других сайтах мне не удалось найти убедительных доказательств того, как Facebook, Twitter и Pinterest генерируют свои идентификаторы. Причина, по которой это необходимо, состоит в том, чтобы избежать коллизий URL. Переход на совершенно другой ID предотвратит это, потому что не будет квадриллионов записей.

  • Facebook.com / имя пользователя / сообщений / 362095193814294
  • Pinterest.com / булавка / 62487513549577588
  • Twitter.com / #! / Имя пользователя / статус / 17994686627061761

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

Чтобы создать похожий идентификатор, но не уникальный, я смог использовать: base_convert(user_id.save_id, 16, 10). Проблема в том, что он не уникален, например: base_convert(15.211, 16, 10) против base_convert(152.11, 16, 10). Эти два одинаковы. Простое объединение двух уникальных наборов чисел все равно приведет к дублированию результатов. Вбрасывание uniqid() в микс по существу исправит дубликаты, но это не кажется хорошей практикой.

Обновление: Twitter, кажется, использует это: https://github.com/twitter/snowflake

Есть предложения по созданию уникального идентификатора, как в приведенных выше примерах?

Ответы [ 3 ]

7 голосов
/ 16 февраля 2012

Предположим, все ваши идентификаторы являются числовыми.Разграничите их символом A (поскольку он, безусловно, не отображается в исходных идентификаторах) и выполните базовое преобразование из base-11 в base-10.:

echo base_convert("15A211", 11, 10); //247820
echo base_convert("152A11", 11, 10); //238140
3 голосов
/ 16 февраля 2012

Комментарий Flickr выше был очень полезен. Мы также используем шардинг. У нас есть поле локатора bigint (int64). Он генерируется путем объединения идентификатора базы данных int (int32) и поля идентификации int (int32).

Если вы знаете, что у вас будет максимальное число баз данных int16 (вполне вероятно), вы можете объединить идентификатор базы данных int16 (smallint) и идентификатор пользователя int32 (int) и идентификатор действия int16 (smallint). Я не знаю разумные цифры для вашего заявления. Но зарезервируйте некоторую часть для идентификатора базы данных, даже если это просто tinyint, так что вы знаете, что в будущем вы будете в безопасности, если добавите больше баз данных.

3 голосов
/ 16 февраля 2012

На самом деле, если вы посмотрите (например) идентификаторы пользователей в ваших Друзьях (в Facebook), вы заметите, что они последовательны среди всех пользователей, точно так же, как поле базы данных AUTO_INCREMENT.Тем не менее, они, вероятно, не начинаются с 1. Мой список друзей, например, имеет некоторые цифры в миллионах, а затем внезапно скачет до 1 триллиона и чего-то еще, поэтому я предполагаю, что значение auto_increment было увеличено - это может быть сделаночтобы «скрыть», сколько именно пользователей.

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

...