Введение
Когда несколько дней назад я разбирал вопросы для интервью, один из вопросов был «Как преобразовать длинный URL в короткий URL и реализовать взаимное преобразование между ними? ", если подумать, то это совершенно не простой вопрос, и тут много аспектов, которые нужно учитывать. Давайте сегодня учиться и учиться вместе с вами!
Короткий URL: как следует из названия, он сокращает длинный URL-адрес до очень короткого URL-адреса, и пользователи, которые посещают этот короткий URL-адрес, могут быть перенаправлены на исходный длинный URL-адрес (то есть процесс восстановления). Это позволяет упростить запоминание и преобразование и часто используется в таких сценариях, как Weibo, QR-код и т. д., которые имеют ограничение по количеству символов.
Что касается сценариев использования коротких URL-адресов, давайте возьмем простой пример, чтобы проиллюстрировать важность использования коротких URL-адресов в бизнесе!
2. Сценарии использования коротких адресов
1, Сина Вейбо
Когда мы публикуем URL-адрес на Sina Weibo, Weibo автоматически идентифицирует URL-адрес и преобразует его, например:t.cn/RuPKzRW. Почему…
Это связано с тем, что Weibo ограничено 140 символами на часть, поэтому, если нам нужно опубликовать несколько ссылок, но ссылка настолько длинная, что занимает почти половину нашего контента, это определенно не разрешено, или пользовательский опыт очень плохой, поэтому появился короткий URL Можно сказать, что сервис коротких URL стал популярен после появления Weibo! Посмотрите вниз:
(1) Сначала я отправляю Weibo с URL-адресом:
(2) Тогда какой эффект отображается после преобразования?(3) Просмотрите исходный код HTML соответствующего элемента страницы следующим образом:(4) Видно, что:blog.CSDN.net/157387 в моем сердце…преобразуется в:t.cn/RuPKzRW, в это время вы…2. Короткий URL-адрес QR-кода
Когда URL-адрес преобразуется в короткий URL-адрес, также может быть сгенерирован соответствующий короткий URL-адрес QR-код.Применение короткого URL-адреса QR-кода, ядра QR-кода, решает проблему кросс-платформенной и кросс-реальной передачи данных; После того, как сцена объединена, можно решить все больше и больше проблем.
(1) Короткий URL-адрес QR-код более удобен, чем короткая ссылка, он может вводить меньше, старайтесь вводить как можно меньше, даже если это всего несколько кликов на клавиатуре, это имеет смысл.
(2) QR-код просто сканирует простую ссылку, но открывает целый мир. Представьте себе покупку товара в торговом автомате с помощью мобильного телефона, сканирование QR-кода происходит немного быстрее, чем поиск торгового автомата с помощью мобильного телефона и нахождение товара, и разве эта операция не более элегантна, чем поиск/нахождение?
(3) Все товары в супермаркете используют штрих-коды для определения уникальности товаров и сканируют штрих-коды, когда вы идете платить. Только представьте, если бы было добавлено больше информации о дате производства, производителе, маршруте обращения, сырье и т. д. продукта, было бы удивительно?Специально для отслеживания информации о продуктах питания сценарии применения QR-кода более обширны.
Преимущества коротких адресов
В дополнение к преимуществам в приведенном выше сценарии, когда мы конвертируем длинные адреса в короткие адреса (сжимая длину URL-адреса), короткие адреса также имеют много практических преимуществ, таких как:
(1) Уменьшите длину URL-адреса и облегчите распространение в социальных сетях. Один из них – сделать URL-адрес короче и его будет легче распространять, особенно если в URL-адресе есть китайские и специальные символы. Короткий URL-адрес решает проблему, связанную с тем, что длинные URL-адреса трудно запомнить и не способствует распространению;
(2) Короткие URL-адреса хорошо открываются и управляются в нашем проекте. Некоторые URL-адреса могут содержать такую информацию, как секс, насилие, реклама и т. д., чтобы мы могли полностью управлять этим соединением с помощью пользовательских отчетов и не отображались в нашем приложении. После передачи алгоритма шифрования на тот же URL-адрес полученный адрес является такой же;
(3) Удобно отслеживать пользовательскую статистику, такую как клики и географическое распределение, в фоновом режиме. Мы можем вести статистику трафика, кликов и другую статистику по ряду URL-адресов, чтобы выявить проблемы большинства пользователей, что поможет нам принять более взвешенные решения о последующей работе над проектом;
(4) Избегать ключевых слов, методов блокировки доменных имен, скрывать реальные адреса и подходить для платных рекламных ссылок;
(5) Вы все еще чувствуете себя комфортно, когда видите 200 символов, таких как «e7x8bv7c8bisdj», за детской ссылкой Taobao? Более того, количество слов в Weibo составляет всего 140. Если количества слов в Weibo или SMS недостаточно, вы можете использовать короткий URL-адрес, чтобы освободить для себя много места;
4. Короткий URL-сервис, предоставляющий платформу
В настоящее время в отечественной сети существует множество платформ, предоставляющих услуги коротких адресов, такие как:
Подождите, их еще много, это можно поискать и их будет много! Но следует отметить, что если вы используете службу коротких адресов определенной платформы, вы должны обеспечить долгосрочную надежную службу, в противном случае она не будет работать в течение определенного периода времени, и URL-адрес, который мы преобразовали ранее, будет закончен!
Взяв Baidu в качестве примера, преобразование адреса нашего блога выше в короткий адрес выглядит следующим образом:
Конечно, для нашего бизнеса было бы лучше, если бы мы могли предоставить свой собственный сервис коротких URL-адресов, не контролируемый другими! (Китайские чипсы должны подняться!!!)
5. Обсуждение того, как создать URL-адрес короткого адреса
Что касается того, как генерировать URL-адреса с короткими адресами, в Интернете существует множество способов, некоторые из которых основаны на сопоставлении, некоторые на основе хэша, а некоторые на основе подписей, но в целом они не подходят для использования в большинстве сценариев, или это это своего рода ошибка метод проектирования. Здесь больше не нужно изобретать велосипед! Ниже перечислены пользователи Zhihu.iammutexПо поводу обсуждения этого вопроса, сделайте скриншот и изучите его вместе с вами:
作者:iammutex
链接:https://www.zhihu.com/question/29270034/answer/46446911
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
В-шестых, сгенерируйте URL-адрес короткого адреса, на который нужно обратить внимание.
Увидев обсуждение вышеупомянутого пользователя iammutex о том, как правильно сгенерировать URL-адрес короткого адреса, мы знаем, что короткий адрес может быть правильно сгенерирован с помощью отправителя числа.Конструктивные точки алгоритма генерации заключаются в следующем:
(1) Используя номеронабиратель, начальное значение равно 0. Для каждого запроса на создание короткой ссылки увеличьте значение номеронабирателя, а затем преобразуйте это значение в шестнадцатеричное (a-zA-Z0-9), например, первое в первый запрос, значение номеронабирателя равно 0, соответствующее шестнадцатеричное значение равно a, значение номеронабирателя во втором запросе равно 1, соответствующее 62-битное значение равно b, а значение номеронабирателя в 10001-м запросе равно 10000, соответствует sBc в шестнадцатеричном формате.
(2) Строковое соединение между доменным именем сервера коротких ссылок и шестнадцатеричным значением номеронабирателя, которое является URL-адресом короткой ссылки, например: t.cn/sBc.
(3) Процесс перенаправления: после создания короткой ссылки необходимо сохранить отношение сопоставления между короткой и длинной ссылками, то есть sBc -> URL.Когда браузер обращается к серверу коротких ссылок, исходная ссылка полученный в соответствии с URL-путем, а затем повторяется 302. Ориентация. Отношение сопоставления можно сохранить с помощью K-V, например Redis или Memcache.
7. Как перейти после генерации короткого адреса?
Для этой части обсуждения мы можем рассматривать ее как весь процесс взаимодействия. Конкретные детали процесса следующие:
(1) Пользователь получает доступ к короткой ссылке:he.talent/RUP kz RW;
(2) Сервер коротких ссылок t.cn получает запрос и получает исходную длинную ссылку в соответствии с URL-путем RuPKzRW (ищите его в базе данных кеша KV):blog.CSDN.net/157387 в моем сердце…
(3) Сервер возвращает код состояния 302 и устанавливает Location в заголовке ответа на:blog.CSDN.net/157387 в моем сердце…
(4) Браузер повторно отправляет запрос на https://blog.csdn.net/xlgen157387/article/details/79863301;
(5) вернуть ответ;
Восемь, схема оптимизации отправителя с коротким адресом
1. Оптимизация алгоритма
При использовании вышеприведенного алгоритма, если не делается никакого суждения, даже для одного и того же исходного URL-адреса, короткие ссылки, генерируемые каждый раз, будут разными, что приведет к пустой трате места в хранилище (поскольку необходимо сохранить сопоставление нескольких коротких ссылок с одним и тем же URL-адресом). Если один и тот же URL-адрес можно сопоставить с одной и той же короткой ссылкой, это может сэкономить место для хранения. Основные идеи заключаются в следующем:
Вариант 1: Посмотрите таблицу
Каждый раз, когда создается короткая ссылка, сначала проверьте, есть ли отношение сопоставления исходного URL-адреса в таблице сопоставления, и если да, верните результат напрямую. Очевидно, что такой подход неэффективен.
Вариант 2: использовать локальный кеш LRU, пространство для времени
Кэш LRU фиксированного размера используется для хранения последних результатов сопоставления N. Таким образом, если ссылка создается очень часто, результат может быть найден в кэше LRU и возвращен напрямую.Это компромисс между объемом памяти и производительностью. .
2. Масштабируемость и высокая доступность
Если сервис генерации коротких ссылок развернут на одной машине, то недостатком является недостаточная производительность, чтобы выдержать массовый одновременный доступ, а второй — то, что он становится единой точкой системы. услуг недоступна.Для решения этой проблемы в системе может быть проведена кластеризация, «шардинг».
В описанной выше системной архитектуре, если отправитель реализован с помощью Redis, Redis является узким местом и единственной точкой системы.Поэтому, используя идею проектирования сегментирования базы данных, можно развернуть несколько экземпляров отправителя, и каждый экземпляр несет ответственность для определенного идентификационного номера.Для нумерации сегментов, например, разверните 10 модулей Redis, каждый из которых отвечает за нумерацию сегментов, заканчивающихся на 0-9.Обратите внимание, что размер шага устройства нумерации должен быть установлен на 10 (количество экземпляров).
Кроме того, хранение отношения сопоставления между длинными ссылками и короткими ссылками также может быть сегментировано.Поскольку нет централизованного хранилища, необходимо разработать дополнительные службы для поиска узла хранения исходной ссылки, соответствующей короткой ссылке. отношение сопоставления на правильном узле.
9. Как реализовать короткий адрес с кодом
1. Используйте случайную последовательность для генерации коротких адресов
Сказав это, я, наконец, перешел к сути.Многие друзья не смогли удержаться, и мне жаль всех разочаровывать.Это всего лишь простая статья, и она не может наглядно продемонстрировать такую сложную систему! Придерживаясь принципа не повторять создание колес, вот один из немногих проектов с открытым исходным кодом, который может реализовать короткие адреса: urlshorter
Примечание: urlshorter сам генерирует короткие адреса на основе случайных методов и не является отправителем коротких адресов, поэтому будут проблемы с производительностью и конфликты, а пользователи ZhihuiammutexРеализация описания все же отличается! И нет лучшего проекта с открытым исходным кодом для справки о способе отправителя короткого адреса!
адрес проекта:git ee.com/tinyframe i...
2. Используйте передатчик SnowFlake для генерации коротких адресов
Ссылка на реализацию:GitHub.com/beyond ситуация… woohoo.wolf be.com/detail/2016…
Алгоритм Snowflake Twitter, SnowFlake, реализован с использованием языка Java.
Алгоритм SnowFlake используется для генерации 64-битных идентификаторов, которые можно просто хранить в виде длинных целых чисел и использовать для генерации уникальных идентификаторов в распределенных системах, а сгенерированные идентификаторы имеют приблизительную последовательность. В этой реализации сгенерированный 64-битный идентификатор можно разделить на 5 частей:
0 - 41位时间戳 - 5位数据中心标识 - 5位机器标识 - 12位序列号
Выделение 5-значного идентификатора центра обработки данных и 5-значного идентификатора машины осуществляется только в текущей реализации.Если у бизнеса есть реальные потребности, их можно выделить в соответствии с другими коэффициентами распределения, такими как требуется идентификатор центра обработки данных.
Код Java реализован следующим образом:
/**
* 进制转换工具,最大支持十进制和62进制的转换
* 1、将十进制的数字转换为指定进制的字符串;
* 2、将其它进制的数字(字符串形式)转换为十进制的数字
* @author xuliugen
* @date 2018/04/23
*/
public class NumericConvertUtils {
/**
* 在进制表示中的字符集合,0-Z分别用于表示最大为62进制的符号表示
*/
private static final char[] digits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
/**
* 将十进制的数字转换为指定进制的字符串
* @param number 十进制的数字
* @param seed 指定的进制
* @return 指定进制的字符串
*/
public static String toOtherNumberSystem(long number, int seed) {
if (number < 0) {
number = ((long) 2 * 0x7fffffff) + number + 2;
}
char[] buf = new char[32];
int charPos = 32;
while ((number / seed) > 0) {
buf[--charPos] = digits[(int) (number % seed)];
number /= seed;
}
buf[--charPos] = digits[(int) (number % seed)];
return new String(buf, charPos, (32 - charPos));
}
/**
* 将其它进制的数字(字符串形式)转换为十进制的数字
* @param number 其它进制的数字(字符串形式)
* @param seed 指定的进制,也就是参数str的原始进制
* @return 十进制的数字
*/
public static long toDecimalNumber(String number, int seed) {
char[] charBuf = number.toCharArray();
if (seed == 10) {
return Long.parseLong(number);
}
long result = 0, base = 1;
for (int i = charBuf.length - 1; i >= 0; i--) {
int index = 0;
for (int j = 0, length = digits.length; j < length; j++) {
//找到对应字符的下标,对应的下标才是具体的数值
if (digits[j] == charBuf[i]) {
index = j;
}
}
result += index * base;
base *= seed;
}
return result;
}
}
/**
* Twitter的SnowFlake算法,使用SnowFlake算法生成一个整数,然后转化为62进制变成一个短地址URL
* @author beyond
* @author xuliugen
* @date 2018/04/23
*/
public class SnowFlakeShortUrl {
/**
* 起始的时间戳
*/
private final static long START_TIMESTAMP = 1480166465631L;
/**
* 每一部分占用的位数
*/
private final static long SEQUENCE_BIT = 12; //序列号占用的位数
private final static long MACHINE_BIT = 5; //机器标识占用的位数
private final static long DATA_CENTER_BIT = 5; //数据中心占用的位数
/**
* 每一部分的最大值
*/
private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);
private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);
private final static long MAX_DATA_CENTER_NUM = -1L ^ (-1L << DATA_CENTER_BIT);
/**
* 每一部分向左的位移
*/
private final static long MACHINE_LEFT = SEQUENCE_BIT;
private final static long DATA_CENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;
private final static long TIMESTAMP_LEFT = DATA_CENTER_LEFT + DATA_CENTER_BIT;
private long dataCenterId; //数据中心
private long machineId; //机器标识
private long sequence = 0L; //序列号
private long lastTimeStamp = -1L; //上一次时间戳
/**
* 根据指定的数据中心ID和机器标志ID生成指定的序列号
* @param dataCenterId 数据中心ID
* @param machineId 机器标志ID
*/
public SnowFlake(long dataCenterId, long machineId) {
if (dataCenterId > MAX_DATA_CENTER_NUM || dataCenterId < 0) {
throw new IllegalArgumentException("DtaCenterId can't be greater than MAX_DATA_CENTER_NUM or less than 0!");
}
if (machineId > MAX_MACHINE_NUM || machineId < 0) {
throw new IllegalArgumentException("MachineId can't be greater than MAX_MACHINE_NUM or less than 0!");
}
this.dataCenterId = dataCenterId;
this.machineId = machineId;
}
/**
* 产生下一个ID
* @return
*/
public synchronized long nextId() {
long currTimeStamp = getNewTimeStamp();
if (currTimeStamp < lastTimeStamp) {
throw new RuntimeException("Clock moved backwards. Refusing to generate id");
}
if (currTimeStamp == lastTimeStamp) {
//相同毫秒内,序列号自增
sequence = (sequence + 1) & MAX_SEQUENCE;
//同一毫秒的序列数已经达到最大
if (sequence == 0L) {
currTimeStamp = getNextMill();
}
} else {
//不同毫秒内,序列号置为0
sequence = 0L;
}
lastTimeStamp = currTimeStamp;
return (currTimeStamp - START_TIMESTAMP) << TIMESTAMP_LEFT //时间戳部分
| dataCenterId << DATA_CENTER_LEFT //数据中心部分
| machineId << MACHINE_LEFT //机器标识部分
| sequence; //序列号部分
}
private long getNextMill() {
long mill = getNewTimeStamp();
while (mill <= lastTimeStamp) {
mill = getNewTimeStamp();
}
return mill;
}
private long getNewTimeStamp() {
return System.currentTimeMillis();
}
public static void main(String[] args) {
SnowFlake snowFlake = new SnowFlake(2, 3);
for (int i = 0; i < (1 << 4); i++) {
//10进制
Long id = snowFlake.nextId();
//62进制
String convertedNumStr = NumericConvertUtils.toOtherNumberSystem(id, 62);
//10进制转化为62进制
System.out.println("10进制:" + id + " 62进制:" + convertedNumStr);
//TODO 执行具体的存储操作,可以存放在Redis等中
//62进制转化为10进制
System.out.println("62进制:" + convertedNumStr + " 10进制:" + NumericConvertUtils.toDecimalNumber(convertedNumStr, 62));
System.out.println();
}
}
}
//生成结果:
10进制:185784275776581632 62进制:dITqmhW2He
62进制:dITqmhW2He 10进制:185784275776581632
10进制:185784284689477632 62进制:dITqw17E6k
62进制:dITqw17E6k 10进制:185784284689477632
10进制:185784284689477633 62进制:dITqw17E6l
62进制:dITqw17E6l 10进制:185784284689477633
10进制:185784284689477634 62进制:dITqw17E6m
62进制:dITqw17E6m 10进制:185784284689477634
10进制:185784284689477635 62进制:dITqw17E6n
62进制:dITqw17E6n 10进制:185784284689477635
10进制:185784284689477636 62进制:dITqw17E6o
62进制:dITqw17E6o 10进制:185784284689477636
10进制:185784284689477637 62进制:dITqw17E6p
62进制:dITqw17E6p 10进制:185784284689477637
10进制:185784284693671936 62进制:dITqw1pfeo
62进制:dITqw1pfeo 10进制:185784284693671936
10进制:185784284693671937 62进制:dITqw1pfep
62进制:dITqw1pfep 10进制:185784284693671937
10进制:185784284693671938 62进制:dITqw1pfeq
62进制:dITqw1pfeq 10进制:185784284693671938
10进制:185784284693671939 62进制:dITqw1pfer
62进制:dITqw1pfer 10进制:185784284693671939
10进制:185784284693671940 62进制:dITqw1pfes
62进制:dITqw1pfes 10进制:185784284693671940
10进制:185784284693671941 62进制:dITqw1pfet
62进制:dITqw1pfet 10进制:185784284693671941
10进制:185784284693671942 62进制:dITqw1pfeu
62进制:dITqw1pfeu 10进制:185784284693671942
10进制:185784284693671943 62进制:dITqw1pfev
62进制:dITqw1pfev 10进制:185784284693671943
10进制:185784284693671944 62进制:dITqw1pfew
62进制:dITqw1pfew 10进制:185784284693671944
Окончательный кодовый адрес:git ee.com/ Hui Lau root/co ...
3. Порекомендуйте универсальный генератор идентификационных номеров
Адрес облака кода:git ee.com/Robert Lee PE…
Здесь указан адрес, а не введение. Если вы хотите узнать больше, вы можете перейти к просмотру документа.
10. Резюме
До сих пор мы вместе изучали, что такое короткие адреса, преимущества коротких адресов, как выбрать правильный способ реализации наших коротких адресов и довольно приличный проект генерации коротких адресов, найденный на CodeCloud. лучшее понимание!
Справочная статья:
1,2CTO.com/Development/201601/4…