Я только что нашел этот отличный учебник, потому что это то, что мне нужно.
Однако, взглянув, кажется, что это может быть неэффективным. Как он работает, сначала создайте уникальный ключ, затем проверьте, существует ли он в базе данных, чтобы убедиться, что он действительно уникален. Однако, чем больше база данных становится медленнее, тем больше функция получает, правильно?
Вместо этого, я подумал, есть ли способ добавить порядок этой функции? Поэтому все, что нужно сделать, это проверить предыдущую запись в БД и увеличить ключ. Так оно всегда будет уникальным?
function generate_chars() { $num_chars = 4; //max length of random chars $i = 0; $my_keys = "123456789abcdefghijklmnopqrstuvwxyz"; //keys to be chosen from $keys_length = strlen($my_keys); $url = ""; while($i<$num_chars) { $rand_num = mt_rand(1, $keys_length-1); $url .= $my_keys[$rand_num]; $i++; } return $url; } function isUnique($chars) { //check the uniqueness of the chars global $link; $q = "SELECT * FROM `urls` WHERE `unique_chars`='".$chars."'"; $r = mysql_query($q, $link); //echo mysql_num_rows($r); die(); if( mysql_num_rows($r)>0 ): return false; else: return true; endif; }
Крошечные люди-url любят использовать случайные токены, потому что тогда вы не можете просто трогать крошечные URL-ссылки. «Куда идет №2?» "О, круто!" «Куда уходит №3?» «Еще холоднее!» Вы можете ввести случайные символы, но вряд ли вы попадете в действительное значение.
Поскольку ключ довольно разреженный (4 значения, каждый из которых имеет 36 * возможности, дает вам 1 679 616 уникальных значений, 5 дает вам 60 466 176) вероятность столкновения небольшая (действительно, это желаемая часть дизайна), и хороший индекс SQL сделает поиск будет тривиальным (действительно, это первичный поиск URL-адреса, поэтому они оптимизируют его).
Если вы действительно хотите избежать поиска и просто unse auto-increment, вы можете создать функцию, которая превращает целое число в строку кажущихся случайными символов с возможностью преобразования обратно. Таким образом, «1» становится «54jcdn», а «2» становится «pqmw21». Подобно Base64-кодированию, но не использует последовательные символы.
(*) Мне на самом деле нравится использовать менее 36 символов – одинарные, без гласных и никаких похожих символов (1, 1, I). Это предотвращает случайные ругательства, а также облегчает кому-то говорить ценность кому-то другому. Я даже сопоставляю аналогичные символы друг другу, принимая «0» для «O». Если вы полностью на машинах, вы можете использовать верхний и нижний регистр и все цифры для еще больших возможностей.
В таблице базы данных есть индекс в поле unique_chars
, поэтому я не понимаю, почему это было бы медленным или неэффективным.
UNIQUE KEY `unique_chars` (`unique_chars`)
Не спешите делать преждевременную оптимизацию на том, что, по вашему мнению, может быть медленным.
Кроме того, может быть некоторая польза в службе сокращения URL-адресов, которая генерирует случайные URL-адреса вместо последовательных URL-адресов.
Я не знаю, почему ты беспокоишься. Предпосылка учебника заключается в создании «случайного» URL-адреса. Если случайное пространство достаточно велико, то вы можете просто полагаться на чистую, тупую удачу. Если случайное пространство символов составляет 62 символа (A-Za-z0-9), то 4 символа, которые они используют, с учетом разумного генератора случайных чисел, равны 1 в 62 ^ 4, что составляет 1 из 14 776 336. Пять символов – 1 в 916,132,832. Итак, конфликт буквально «1 в миллиарде».
Очевидно, что по мере заполнения документов ваши шансы увеличиваются на вероятность столкновения.
Имея 10 000 документов, это 1 из 91 613, почти 1 из 100 000 (для круглых номеров).
Это означает, что для каждого нового документа у вас есть 1 из 91,613 шансов попасть в БД еще раз для другого вытащить игровой автомат.
Он не детерминирован. Это случайное. Это удача. Теоретически вы можете поразить строку действительно, действительно, неудачу и просто столкнуться после столкновения после столкновения. Кроме того, он, в конце концов, заполнит. Сколько URL-адресов вы планируете использовать для хэширования?
Но если 1 из 91,613 коэффициентов недостаточно хорош, увеличение его до 6 символов делает его более 1 в 5 М за 10 000 документов. Мы говорим здесь почти о LOTTO.
Проще говоря, сделайте ключ достаточно большим (7 символов? 8?), И проблема в значительной степени «желает» сама по себе.
Не могли бы вы закодировать URL как Base36, когда он сгенерирован, а затем декодировать его при посещении – что позволит вам полностью удалить базу данных?
Отрывок из Channel9 :
Формула проста, просто верните идентификатор записи нашего сообщения, который длинный в короткую строку с помощью Base-36, кодирующей его, а затем привяжите « http://ch9.ms/ » на передней панели. Это дает достаточно короткие URL-адреса и может быть вычислено с любого конца без необходимости поиска базы данных. В результате URL-адрес, подобный http://ch9.ms/A49H , затем используется при создании ссылки Twitter.
Я решил аналогичную проблему, выполнив alogirthm, который использовался для генерации серийных номеров один за другим в base36 . У меня была собственная oredring символов base36, каждая из которых уникальна. Поскольку он генерировал числа серийно, мне не пришлось беспокоиться о дублировании. Сложность и случайность числа зависит от упорядочения чисел base36 [символов] … что тоже для публики только потому, что для моего приложения они серийные номера 🙂
Проверьте эти функции парней – http://www.pgregg.com/projects/php/base_conversion/base_conversion.php source – http://www.pgregg.com/projects/php/base_conversion/base_conversion.inc.phps
Вы можете использовать любую базу, которая вам нравится, например, для преобразования 554512 в базовую 62, вызов
$tiny = base_base2base(554512, 10, 62);
и это оценивается до $tiny = '2KFk'
.
Итак, просто перейдите в уникальный идентификатор записи базы данных.
В проекте я использовал это в удалении нескольких символов из строки $sChars
и использую базу 58. Вы также можете изменить символы в строке, если хотите, чтобы значения были менее легко угадать.
Вы, конечно, можете добавить заказ, просто указав URL-адреса:
http://mytinyfier.com/1 http://mytinyfier.com/2
и так далее. Но если хеш-ключ индексируется в базе данных (что, очевидно, должно быть), повышение производительности будет в лучшем случае минимальным.
Используйте автоинкремент в базе данных и получите последний идентификатор, как описано http://www.acuras.co.uk/articles/24-php-use-mysqlinsertid-to-get-the-last-entered-auto-increment- стоимость
Я бы не стал делать упорядоченное перечисление по двум причинам:
1) SQL-серверы очень эффективны при проверке таких хэш-коллизий (с учетом правильных индексов)
2) Это может повредить конфиденциальности, так как пользователи смогут легко определить, что другие пользователи используют.
Возможно, это немного не ответ, но мое общее правило для создания всегда уникальных ключей – это просто md5 (time () * 100 + rand (0, 100)); Есть шанс на 100 000, если два человека используют одну и ту же услугу за одну секунду, они получат тот же результат (что невозможно).
Тем не менее, md5 (rand (0, n)) тоже работает.
Это может сработать, но самый простой способ решить проблему, вероятно, будет с хешированием. Теоретически говоря, хеширование выполняется в O (1) раз, как и в, оно только должно выполнять хеш, а затем только одно фактическое попадание в базу данных для извлечения значения. Затем вы должны ввести осложнения для проверки хеш-коллизий, но похоже, что это, вероятно, то, что делают большинство провайдеров tinyurl. И хорошая хэш-функция не так уж трудно писать.
Я также создал небольшую услугу tinyurl.
Я написал сценарий в Python, который генерировал ключи и хранил в таблице MySQL имена tokens со статусом U (Unused).
Но я делаю это в автономном режиме. У меня есть кукуруза на моем VPS. Он запускает скрипт каждые 10 минут. Скрипт проверяет, есть ли в таблице менее 1000 ключей, он продолжает генерировать ключи и вставлять их, если они уникальны и не существует в таблице, пока количество ключей не достигнет 1000.
Для моего обслуживания 1000 клавиш в течение 10 минут более чем достаточно, вы можете установить время или количество ключей, сгенерированных в соответствии с вашими потребностями.
Теперь, когда на моем веб-сайте должен быть создан какой-либо крошечный URL-адрес, мой PHP-скрипт просто извлекает любой ключ, который не используется из таблицы и отмечен его статусом как T (принято). PHP-скрипт не должен беспокоиться о своей уникальности, так как мой скрипт python уже заполнял только уникальные ключи.
Не могли бы вы просто обрезать хэш по желанию?
$tinyURL = substr(md5($longURL . time()),0,4);
Конечно, это может не обеспечить столько псевдослучайности, сколько использовать всю длину строки. Но, если вы hash длинный URL-адрес, объединенный с time()
, не будет ли этого достаточно? Мысли об использовании этого метода? Благодаря!