偶然的一次业务需求,需要使用到这样的功能。虽然很多大平台提供了这样的接口(新浪,百度等等)。但是还是对其中的原理想在梳理一下。

我们不妨先来看一下短链接服务的整个流程,以前面提到的微博短网址服务为例。用户输入想要缩短的长网址,转化后得到一个以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字段,保存长网址的哈希值,并通过查找哈希值来判断条目是否存在,提高查找的效率。

以上就是短链接服务的基本实现方法,最核心的其实就是多进制的使用。

当然网上还有一种对于这种功能实现最优的方法。

最优的算法

通过发号原理

顾名思义这个系统的第一个请求过来了,我们以微博为例,短链接系统的第一个请求我们可以给变为t.cn/0,第二个t.cn/1等等;
实现的方式也会很简单
1、小型的系统用MySQL的自增索引就可以满足。
2、大型系统可以考虑分布式key-value系统。

存储原理

发号策略是这样的,当一个新的链接过来时,发号器发一个号与之对应。往后只要有新链接过来,发号器不停发号就好。举个例子,第一个进来的链接发号器发0号,对应的短链接为 xx.xxx/0,第二个进来的链接发号器发1号,对应的短链接为 xx.xxx/1,以此类推。
发号器发出的10进制号需要转换成62进制,这样可以大大缩短号码转换成字符串后的长度。比如发号器发出 10,000,000,000 这个号码,如果不转换成62进制,直接拼接在域名后面,得到这样一个链接 xx.xxx/10000000000。将上面的号码转换成62进制,结果为AOYKUa,长度只有6位,拼接得到的链接为 xx.xxx/AOYKUa。可以看得出,进制转换后得到的短链接长度变短了一些。6位62进制数,对应的号码空间为626,约等于568亿,所以基本上不用担心发号器无号可发的情况。

高并发场景下

上面设计看起来有一个单点,那就是发号器。如果做成分布式的,那么多节点要保持同步加1,多点同时写入。这样难以避免产生单点性能瓶颈。因此我们可以考虑将单点变为多点。我们可以引入多个机器,我们可以设定机器A发号只发向100取余等于0的数字100n,同理机器B只发向100取余等于1数字 100n+1,以此类推,各个机器相互独立互不干扰,我们可以随时扩展我们的机器了。

同一长链接,每次转成的短链接是否一样

同一长链接,每次转成的短链接不一定一样,原因在于如果查询缓存时,如果未命中,发号器会发新号给这个链接。需要说明的是,缓存应该缓存经常转换的热门链接,假设设定缓存过期时间为一小时,如果某个链接很活跃的话,缓存查询命中后,缓存会刷新这个链接的存活时间,重新计时,这个链接就会长久存在缓存中。
我们也可以引入LRU算法。进行淘汰我们不经常使用到的链接。

重定向问题

选取301,还是302?
301是永久重定向,302是临时重定向。

如果选择301:短地址生成以后就不会变化,所以用301是符合http语义的。同时对服务器压力也会有一定减少。这样一来,我们就无法统计到短地址被点击的次数了。
如果选择302:选择302虽然会增加服务器压力,但是可以统计到短地址被点击的次数了,我可以针对点击的次数来进行后期的大数据处理,机器学习,以及推荐算法。
选择302还是301,想必读者心中有肯定有数了。

以上就是我看到网上的一下帖子。特此放在一起。也算做个参考吧。虽然是一个很小的需求,但是还是有的深究的。

长链接转短链接的一次尝试相关推荐

  1. 什么是长连接和短连接?(长链接、短链接)什么时候使用长连接、短链接?

    文章目录 什么是长连接和短连接? 什么时候使用长连接.短链接? 定义 适用场景 什么是长连接和短连接? 在HTTP/1.0中默认使用短连接.也就是说,客户端和服务器每进行一次HTTP操作,就建立一次连 ...

  2. http / 关于长连接和短链接的理解

    HTTP 协议是基于请求 / 响应模式的,因此只要服务端给了响应,本次 HTTP 请求就结束了,也可以理解成 HTTP 是面向请求 / 响应的. TCP 协议是面上连接的. 综上,如果 HTTP 请求 ...

  3. HTTP的长链接和短链接说明

    HTTP的长链接和短链接实际上是TCP的长连接和短链接.首先我们先介绍一下TCP/IP协议组四层模型.其中包括以下: 应用层:HTTP.FTP.DNS.TELNET等协议 传输层:TCP.UDP 网络 ...

  4. java,url长链接生成短链接,短链接生成器,自定义字符串,对字符串md5混合KEY加密,根据短链接获得key值,不重复的随机数,不重复的随机字符串...

    java,url长链接生成短链接,短链接生成器,自定义字符串,对字符串md5混合KEY加密,根据短链接获得key值,不重复的随机数,不重复的随机字符串 1 package com.zdz.test; ...

  5. 【短链接】——新浪、百度、搜狐等官方长链接转短链接

    在项目中难免会生成自己的跳转链接,为了简化链接以及防止微信等屏蔽,可以用一些官方的api将自己的链接转为短链接. ConvertShortUrlUtil.java public class Conve ...

  6. C#长链接转短链接(调用新浪api)

     /// <summary>  /// 长链接转短链接  /// </summary>  /// <param name="longUrl"> ...

  7. 我把视频变成链接_如何把长链接变成短链接?3个工具帮你实现

    不管是文章还是视频的链接,很多时候都是长长的一串,如果是发给别人的话,就会显得啰里啰嗦,占用空间大不说,还非常难看,使用起来不方便.其实长链接也是能够变成短链接的,下面就带来三个工具,让链接变得美观又 ...

  8. 长URL链接转短链接算法

    引言 很多大型网站都加入了短链接的功能.之所以要是使用短链接,主要是因为微博只允许发140 字,如果链接地址太长的话,那么发送的字数将大大减少.短链接的主要职责就是把原始链接很长的地址压缩成只有6 个 ...

  9. 微信URL Scheme码+长链接转短链接+短链接通过h5页面跳转到微信小程序

    微信URL Scheme码+长链接转短链接+短链接通过h5页面跳转到微信小程序 --生成微信URL Scheme码-->长链接转换成短链接-->通过短信进行推广-->用户访问营销短信 ...

  10. php 长链接变为短链接,长链接转短链接原理

    长链接转短链接代码: function short_url($input = '', $salt = '') { $base62 = array ('a', 'b', 'c', 'd', 'e', ' ...

最新文章

  1. hibernate mysql 存储过程_hibernate调用mysql存储过程
  2. vue 3.0和2.0区别_一文看懂 Vue.js 3.0 的优化
  3. java并发之线程封闭(二)
  4. ubuntu15.04配置php,Linux_Ubuntu 15.04上安装Justniffer的详细教程,Justniffer 是一个可用于替代 Snor - phpStudy...
  5. bzoj千题计划169:bzoj2463: [中山市选2009]谁能赢呢?
  6. rocketmq常用命令
  7. C#反射取得方法、属性、变量
  8. 散射回波仿真Matlab,基于matlab的体目标回波模拟方法与流程
  9. Matplotlib 全部笔记的思维导图精简记忆版
  10. sql语句练习50题(经典)
  11. 电脑ps4,Windows电脑玩PS4游戏,索尼:先来升级Win10吧
  12. Ubuntu12.04 Thinkpad T410i 安装记录 持续更新...
  13. 在vue中如何使用umy-ui
  14. visual paradigm 绘图学习记录
  15. Flutter 画笔绘制二维码扫描框
  16. 高等数学(第七版)同济大学 习题1-3 个人解答
  17. 网站让浏览器崩溃的原因有哪些
  18. 如何创建一个“个人微信公众号”
  19. 实用项目管理-干系人管理
  20. 让我们和机器一起聊天

热门文章

  1. 怎么用计算机做模型,如何运用ArcScene制作简洁的三维建模
  2. 实现移动曲面拟合法的数字高程模型内插,数据格式X、Y、Z,数据量大,使用C++语言实现...
  3. YAMAHA 钢琴型号与年代对应表
  4. 计算机导论课前演讲稿,课前三分钟演讲稿(精选6篇)
  5. hadoop配置文件详解系列(一)-core-site.xml篇
  6. 轻流程:IT团队的积分式绩效管理读后
  7. 1w存银行一年多少利息_每年拿出1万元存在银行,5年之后本金和利息一共是多少?...
  8. Echarts柱状图(顶部和内部的数值显示)/(内部数值的百分比计算)/(顶部显示多行数据)/(柱体圆角)
  9. 树莓派python蓝牙_树莓派的蓝牙操作
  10. mysql:数据库设计