网页短链接是指将原本较长的网址转化成较短的网址,从而便于用户的记忆与社交软件上的传播。很多互联网公司都提供了生成短链接的服务,比如新浪微博短网址服务等,本文就来聊聊实现短链接服务的基本原理。
我们不妨先来看一下短链接服务的整个流程,以前面提到的微博短网址服务为例。用户输入想要缩短的长网址,转化后得到一个以http://t.cn
开头的短网址,然后用户将该链接通过微信或者微博等方式分享给朋友,其他人点击之后即可进入原本长网址所对应的页面。整个流程如下图所示:
从图中可以很清楚地看到,实现短链接服务的关键是两个步骤:1、如何把一个任意长的字符串转化成一个较短的字符串;2、从短网址如何还原出长网址。第一个问题很容易让人想到哈希算法,通过一定的方式将任意长的文本转化成一个固定长度的字符串,只要目标字符串的长度适当,那么不同的输入几乎不可能对应同一个字符串。不过这么做有个缺点就是无法从得到的结果还原输入的字符串,因此不适用于我们的场景。但基于哈希算法的思想,我们可以设计一种以多进制为基础的算法完成这个任务。
具体而言,我们可以创建一个用于保存长网址的数据表,比如就叫Url,这张表很简单,只需要两个字段,一个主键
用于保存id
,一个url
字段用于存放原始的长网址,每个长网址都在这张表有一条记录。当进行长网址转换时,先检查数据表中是否存在该长网址,若是直接获取该记录的id
,否则在数据表中创建一条新记录,并返回其id
。对于这个id
,我们可以得到一个多进制表示下的新值,比如在以“0-9a-z”这36个字符表示的36进制中,一亿
这个数字可以被表示成1njchs
,只需要6个字符即可,将这6个字符拼接到准备好的域名后即可得到一个对应的短网址返回给用户。由于一亿个网址只需要6个字符,因此这种方式足够满足大部分网站的需求。
而当用户点击了我们生成的短网址后,只需要将代表多进制的这部分提取出来,还原成十进制的数字后查表即可得到原始的长网址,再根据网址做一个重定向即可让用户访问到原始的网页。具体的实现可以参考下面的typescript
代码
// 将原始的长链接通过36进制转化为短链接
export async function long2short(url: string) {
if (!url.startsWith('http://') && !url.startsWith('https://')) {
throw new Error('Invalid url');
}
if (url.startsWith(config.shortLinkBaseUrl)) {
return url;
}
let item = await Url.getByUrl(url);
if (!item) {
item = await Url.create(url);
}
return config.shortLinkBaseUrl + item.id.toString(36);
}
// 将短链接还原为真实的长链接
export async function short2long(url: string) {
let item = await Url.select(Number.parseInt(url, 36));
if (!item) {
throw new Error('Invalid url');
}
return item.url;
}
这里的config.shortLinkBaseUrl
也就是我们用来做短链接服务的域名,在前面的例子中就是http://t.cn
,我们需要在这个域名对应的服务器内实现短链接的服务,同时这个域名本身不能太长,否则就失去了它的意义。另外还有一点值得注意,就是在根据长网址去数据表查找它是否存在时,因为长网址可以任意长,因此直接用它作为索引在数据表中查找的话效率较低,可以考虑在表中增加一个hash
字段,保存长网址的哈希值,并通过查找哈希值来判断条目是否存在,提高查找的效率。
以上就是短链接服务的基本实现方法,最核心的其实就是多进制
的使用,有兴趣的朋友可以自己动手试试看,有任何问题欢迎留言交流。