Я всегда задавался вопросом, как и почему они это делают … пример: http://youtube.com/watch?v=DnAMjq0haic
Как генерируются эти идентификаторы, чтобы дубликатов не было, и какое преимущество у этого есть при наличии простого автоматического увеличения числового идентификатора?
Как держать его коротким, но все же сохранить его уникальность? Строка uniqid создается довольно долго.
Кевин ван Зонневельд написал отличную статью, в том числе функцию PHP, чтобы сделать именно это. Его подход – лучшее, что я нашел, исследуя эту тему.
Его функция довольно умна. Он использует фиксированную переменную индекса, поэтому проблемные символы могут быть удалены (например, гласные или избегать путаницы O и 0). Он также имеет возможность обфускации идентификаторов, чтобы они не были легко угадываемы.
Попробуйте следующее: http://php.net/manual/en/function.uniqid.php
uniqid – Создать уникальный идентификатор …
Получает префиксный уникальный идентификатор, основанный на текущем времени в микросекундах.
Внимание. Эта функция не генерирует криптографически защищенные значения и не должна использоваться для криптографических целей. Если вам требуется криптографически безопасное значение, попробуйте вместо этого использовать random_int () , random_bytes () или openssl_random_pseudo_bytes () .
Предупреждение Эта функция не гарантирует уникальность возвращаемого значения. Поскольку большинство систем настраивает системные часы по NTP или тому подобное, системное время постоянно изменяется. Поэтому возможно, что эта функция не возвращает уникальный идентификатор для процесса / потока. Используйте
more_entropy
чтобы повысить вероятность уникальности …
base62 или base64 кодируют значение вашего первичного ключа, а затем сохраняют его в другом поле.
пример base62 для первичного ключа 12443 = 3eH
сохраняет некоторое пространство, поэтому я уверен, что youtube использует его.
выполнение кодировки base62 (A-Za-z0-9) на вашем ПК или уникальный идентификатор предотвратит накладные расходы, связанные с необходимостью проверить, существует ли ключ уже существует 🙂
У меня была аналогичная проблема – у меня был первичный идентификатор в базе данных, но я не хотел раскрывать их пользователю – было бы лучше показать какой-то хэш вместо этого. Итак, я написал хешиды.
Документация: http://www.hashids.org/php/
Souce: https://github.com/ivanakimov/hashids.php
Хэши, созданные с этим классом, уникальны и дешифруемы. Вы можете предоставить собственное значение соли, чтобы другие не могли расшифровать ваши хэши (а не то, что это большая проблема, но все же «хорошая возможность»).
Чтобы зашифровать номер, вы сделаете следующее:
require('lib/Hashids/Hashids.php'); $hashids = new Hashids\Hashids('this is my salt'); $hash = $hashids->encrypt(123);
Теперь ваш $hash
будет: YDx
Вы также можете задать минимальную длину хэша как второй параметр для конструктора, чтобы ваши хэши могли быть длиннее. Или, если у вас сложная кластерная система, вы можете даже зашифровать несколько чисел в один хэш:
$hash = $hashids->encrypt(2, 456); /* aXupK */
(например, если у вас есть пользователь в кластере 2 и объект с первичным идентификатором 456 ). Расшифровка работает одинаково:
$numbers = $hashids->decrypt('aXupK');
$numbers
будет тогда: [2, 456]
.
Хорошая вещь об этом – вам даже не нужно хранить эти хеши в базе данных. Вы можете получить хэш из url, как только запрос поступит и расшифрует его на лету, – а затем вытащите первичный идентификатор из базы данных (что, очевидно, является преимуществом в скорости).
То же самое с выходом – вы можете зашифровать идентификатор на выходе и отобразить хэш пользователю.
EDIT :
Автоинкремент можно легко сканировать. Они не могут быть предсказаны и, следовательно, не могут быть последовательно сканированы.
Я предлагаю использовать формат с двойным URL-адресом (подобно URL-адресам SO):
yoursite.com/video_idkey/url_friendly_video_title
Если вам нужен как идентификатор, так и заголовок в URL-адресе, вы можете использовать простые номера, такие как 0001, 0002, 0003 и т. Д.
Создание этих ключей может быть очень простым. Вы можете использовать функцию uniqid () в PHP для генерации 13 символов или 23 с большей энтропией.
Если вы хотите, чтобы короткие URL-адреса и предсказуемость не вызывали беспокойства, вы можете преобразовать автоматически увеличивающийся идентификатор в более высокую базу .
Вот небольшая функция, которая каждый раз генерирует уникальный ключ. У него очень мало шансов повторить тот же уникальный идентификатор.
function uniqueKey($limit = 10) { $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; $randstring = ''; for ($i = 0; $i < $limit; $i++) { $randstring .= $characters[rand(0, strlen($characters))]; } return $randstring; }
source: генерировать случайные уникальные идентификаторы, такие как YouTube или TinyURL в PHP
Подумайте, используя что-то вроде:
$ id = base64_encode (md5 (uniqid (), true));
uniqid предоставит вам уникальный идентификатор. MD5 рассеет его, что даст вам 128-битный результат. Base 64, которое даст вам 6 бит на символ в идентификаторе, подходящем для использования в Интернете, весом около 23 символов и вычислительно трудноразрешимым. Если вы хотите быть еще более параноидальным уградом от md5 до sha1 или выше.
Способ сделать это – хеш-функция с уникальным входом каждый раз.
пример (вы отметили вопрос с помощью php therfore):
$uniqueID = null do { $uniqueID = sha1( $fileName + date() ); } while ( !isUnique($uniqueID) )
Для создания этих идентификаторов должна быть библиотека для PHP. Если нет, это не сложно реализовать.
Преимущество состоит в том, что позже у вас не будет конфликтов имен, когда вы попытаетесь реорганизовать или объединить различные серверные ресурсы. С числовыми идентификаторами вам придется изменить некоторые из них для разрешения конфликтов, и это приведет к изменению Url, приводящему к удалению SEO.
Большая часть этого зависит от того, что вам нужно делать. Как уникален уникальный? Вы обслуживаете уникальные идентификаторы, и они что-то означают в вашей БД? если это так, последовательный # может быть в порядке.
С другой стороны, если вы используете последовательный #, кто-то может систематически украсть ваш контент, итерации по номерам.
Существуют команды файловой системы, которые будут генерировать уникальные имена файлов – вы можете использовать их.
Или GUID.
Результаты хеш-функций, таких как SHA-1 или MD5 и GUID, как правило, становятся очень длинными, что, вероятно, является тем, чего вы не хотите. (В качестве примера вы конкретно упоминали о YouTube: их идентификаторы остаются относительно короткими даже при использовании видеороликов bazillion, которые они размещают.)
Вот почему вы можете захотеть преобразовать ваши числовые идентификаторы, которые вы используете за кулисами, в другую базу при размещении их в URL-адресах. Например, Flickr использует Base58 для своих канонических коротких URL-адресов. Подробная информация об этом доступна здесь: http://www.flickr.com/groups/api/discuss/72157616713786392/ . Если вы ищете универсальное решение, посмотрите на пакет PEAR Mathe_Basex.
Обратите внимание, что даже в другой базе идентификаторы все еще могут быть предсказаны вне вашего приложения.
У меня нет формулы, но мы делаем это в проекте, в котором я нахожусь. (Я не могу поделиться им). Но мы в основном генерируем один символ за раз и добавляем строку.
Как только у нас будет завершенная строка, мы проверим ее против базы данных. Если нет другого, мы идем с ним. Если это дубликат, мы начинаем процесс. Не очень сложно.
Преимущество в том, что я предполагаю, что GUID .
Это НЕ PHP, но может быть преобразован в php или как это Javascript и так клинсиде без необходимости замедлять работу сервера. Его можно использовать, когда вы публикуете все, что вам нужно, уникальный идентификатор вашего php.
Вот способ создания уникальных идентификаторов, ограниченных
9 007 199 254 740 992 unique id's
он всегда возвращает 9 charachters.
где iE2XnNGpF
составляет 9 007 199 254 740 992
Вы можете кодировать длинное Number
а затем декодировать 9char сгенерированную String
и возвращать номер.
в основном эта функция использует индекс 62base Math.log () и Math.Power, чтобы получить правильный индекс, основанный на номере. Я бы объяснил больше о функции, но, если это произошло некоторое время назад и больше не может найти сайт, и это toke мне очень долго, чтобы понять, как это работает … в любом случае я переписал функцию из 0 .. и этот в 2-3 раза быстрее, чем тот, который я нашел. i зациклил на 10 миллионов, проверяя, совпадает ли номер с процессом декодирования, и он toke 33sec с этим, а другой 90 секунд.
var UID={ ix:'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ', enc:function(N){ N<=9007199254740992||(alert('OMG no more uid\'s')); var M=Math,F=M.floor,L=M.log,P=M.pow,r='',I=UID.ix,l=I.length,i; for(i=F(L(N)/L(l));i>=0;i--){ r+=I.substr((F(N/P(l,i))%l),1) }; return UID.rev(new Array(10-r.length).join('a')+r) }, dec:function(S){ var S=UID.rev(S),r=0,i,l=S.length,I=UID.ix,j=I.length,P=Math.pow; for(i=0;i<=(l-1);i++){r+=I.indexOf(S.substr(i,1))*P(j,(l-1-i))}; return r }, rev:function(a){return a.split('').reverse().join('')} };
,var UID={ ix:'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ', enc:function(N){ N<=9007199254740992||(alert('OMG no more uid\'s')); var M=Math,F=M.floor,L=M.log,P=M.pow,r='',I=UID.ix,l=I.length,i; for(i=F(L(N)/L(l));i>=0;i--){ r+=I.substr((F(N/P(l,i))%l),1) }; return UID.rev(new Array(10-r.length).join('a')+r) }, dec:function(S){ var S=UID.rev(S),r=0,i,l=S.length,I=UID.ix,j=I.length,P=Math.pow; for(i=0;i<=(l-1);i++){r+=I.indexOf(S.substr(i,1))*P(j,(l-1-i))}; return r }, rev:function(a){return a.split('').reverse().join('')} };
Поскольку я хотел 9-символьную строку, я также добавлял 's на сгенерированную строку, которая равна 0
.
Чтобы закодировать число, вам нужно передать Number
а не строку.
var uniqueId=UID.enc(9007199254740992);
Чтобы снова декодировать номер, вам необходимо передать 9-шаровую сгенерированную String
var id=UID.dec(uniqueId);
вот некоторые цифры
console.log(UID.enc(9007199254740992))//9 biliardi o 9 milioni di miliardi console.log(UID.enc(1)) //baaaaaaaa console.log(UID.enc(10)) //kaaaaaaaa console.log(UID.enc(100)) //Cbaaaaaaa console.log(UID.enc(1000)) //iqaaaaaaa console.log(UID.enc(10000)) //sBcaaaaaa console.log(UID.enc(100000)) //Ua0aaaaaa console.log(UID.enc(1000000)) //cjmeaaaaa console.log(UID.enc(10000000)) //u2XFaaaaa console.log(UID.enc(100000000)) //o9ALgaaaa console.log(UID.enc(1000000000)) //qGTFfbaaa console.log(UID.enc(10000000000)) //AOYKUkaaa console.log(UID.enc(100000000000)) //OjO9jLbaa console.log(UID.enc(1000000000000)) //eAfM7Braa console.log(UID.enc(10000000000000)) //EOTK1dQca console.log(UID.enc(100000000000000)) //2ka938y2a
Как вы можете видеть, есть много, и вы не хотите этого … так что начните с большого числа. предположим, что вы DB id 1 .. просто добавьте 100000000000000
так что у вас есть 100000000000001
и ваш уникальный идентификатор выглядит как идентификатор youtube 3ka938y2a
я не думаю, что легко выполнить другие 8907199254740992
уникальные идентификаторы