网页短链接实现原理探究

事情是这样的,今天一人问我一个问题,但是我懒得在说,就在网上找了一篇博客通过QQ发送给他,但是在发送链接时我发现之前很长的链接变成了短链接,且这个短链接能够正常访问之前的长链接,好奇之下就有了这篇文章.


什么是短链接?

我的理解就是通过一定的算法和技术实现将原本很长的网址转换为较短的网址,从而便于用户记忆和在互联网上的传播.常用于有字数约束的微博,二维码等场景.

现在很多公司都提供了短链接服务,比如百度,新浪微博等等,以供用户自由方便的生成短链接.

短链接的大致整体流程

今天上午我找的原本链接是这个:

https://blog.wpjam.com/m/scripts-and-plugins-for-analyzing-website-traffic-stats/

生成的短链接(长期的话可能会无效):

http://url.cn/5r8GoSZ

大致流程是这样的:我复制(输入)了一个长链接,通过腾讯服务器的转化后得到一个以http://url.cn开头的短链接,然后我可以将该网址在互联网上进行分享和传播,其他人在访问该短网址可以进入到之前原本长网址对应的页面.​

自己画的,凑合着看

 所以要想将生成短链接,我们需要注意两个问题:

如何将任意长的字符串转化为较短长或者固定长的字符串.

 如何将短链接还原成之前的长链接,使之能够访问.

算法实现

Hash实现

通过一定方式将任意长的文本转化为一个固定长的字符串,只要目标文本长度适当,那么我们对于不同的输入通过哈希几乎(注意是几乎)不可能得到对应同一个字符串.通过对长链接进行Hash运算,将Hash值作为这个长链接的唯一标示.但是通过Hash实现可能会造成碰撞.不一样的长网址缩短成了同一个短网址,那也就做不到复原了.

对于碰撞问题,有一种缓冲方法就是在呈现碰撞了以后后边在增加随机字符,随机字符的增加能够缓解碰撞的疑问,但是这终究是一种缓冲的办法,没有彻底解决碰撞.

自增序列算法(永不重复算法)

我们可以设置一个自增id,对于每一个新的长链接给他一个不重复的id.

原理:当服务器接收到一个网址时首先检验这个网址在服务器中是否再存,如果不存在,存储这个新网址并分发一个id,这个id设置成自增,保证了每一个存储的网址的id都是唯一标示.比如上面的,当一个链接过来时,给这个链接发一个0,再有一个链接过来时,给后面这个链接一个1,以此类推.

数据实现:我们发现短链接后面的参数好像都是定长的,但是如果通过id进行时,参数不定长,且随着id的自增,可能会出现这种情况:url.cn/10000000.我们可以将十进制的id转化为多进制,比如在以'0-9a-z'这36个字符表示的36进制中,一亿可以被表示为1njchs,基本实现不重复够用.如果数据量更大,我们可以采用62进制进行转化:


网上找的

​​

短址的长度一般设为 6 位,而每一位是由[a - z, A - Z, 0 - 9]总共 62 个字母组成的,所以 6 位的话,总共会有 62^6 ~= 568亿种组合。

存储实现

对于小型系统,简单的mysql系统的表自增索引即可实现(注意自增id数据类型,int只能到65535)

大型系统可以搭建分布式key-value系统进行存储.

我使用mysql简单建了一张表,用于保存长网址的数据,只有两个字段,一个是主键用于保存id,一个url字段用于存放原始的长网址.在进行长网址转换时,先检查数据表中是否存在该长网址,如果存在直接获取该记录的id,否在创建一条新的记录并返回该记录的id,对于这id进行进制转化处理后拼接到准备好的域名后面得到一个对应的短网址返回给用户.

这里我简单模仿了一个转换短链接的功能:

url.php:用于模拟数据库存储

<?php

return array(

    'http://test1.com/12345vn6',

    'http://test2.com/1234gf56',

    'http://teat1.com/123ssgg456',

    'http://test1.com/1234svss56',

    'http://tefasfd1.com/123456',

    'http://tesddt1.com/12sss3456',

    'http://tehghdgst1.com/123dsaf456',

    'http://tedddst1.com/12SDsd3456',

    'http://testaa1bb.com/1234ccgfryh56',

    'http://testaa1dfd.com/1234ccgfryh56',

    'http://testaa1.com/1234ccgfryh56',

    'http://testaa1.cssom/1234ccgfryh56',

    'http://testaa1.com/1234ccgfryh56',

    'http://testraa1.com/1234ccgfryzh56',

    'http://teffstaa1.com/1234ccgfsryh56',

    'http://testaxxa1.com/1234ccgfrsryh56',

    'http://testaa1ll.com/1234ccgyrfryh56',

    'http://testaa1.com/1234ccgfryyh56',

    'http://tesbbtaa1.com/1ss234cjcgfryh56',

)

?>

get.php:用于模拟生成短链接

<?php

    require './jinzhi.php';

    $arr = include('./url.php');

    $host = 'http://url.cn/';

    $url = $_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'];

    $keyId = in_array($url, $arr) ? array_search($url, $arr) : (array_push($arr, $url) - 1);

    $toKey = get_char($keyId);

    echo $host . $toKey;

?>

jinzhi.php:模拟进制转化

<?php

/**

* @desc  im:十进制数转换成三十六机制数

* @param (int)$num 十进制数

* return 返回:三十六进制数

*/

function get_char($num) {

    $num = intval($num);

    if ($num <= 0)

        return false;

    $charArr = array("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');

    $char = '';

    do {

        $key = ($num - 1) % 36;

        $char= $charArr[$key] . $char;

        $num = floor(($num - $key) / 36);

    } while ($num > 0);

    return $char;

}

/**

* @desc  im:三十六进制数转换成十机制数

* @param (string)$char 三十六进制数

* return 返回:十进制数

*/

function get_num($char){

$array=array("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");

$len=strlen($char);

for($i=0;$i<$len;$i++){

$index=array_search($char[$i],$array);

$sum+=($index+1)*pow(36,$len-$i-1);

}

return $sum;

}

?>


进行路由请求:http://localhost:4000/get.php/10000000

输出:http://url.cn/J

至于解析短链接跳转至原有链接,只是对上面思路进行取反.

摘要算法

实现思路:

将长网址md5生成 32 位签名串,分为 4 段, 每段 8 个字节

对这四段循环处理, 取 8 个字节, 将他看成 16 进制串与 0x3fffffff(30位1) 与操作, 即超过 30 位的忽略处理

这 30 位分成 6 段, 每 5 位的数字作为字母表的索引取得特定字符, 依次进行获得 6 位字符串

总的md5串可以获得 4 个 6 位串,取里面的任意一个就可作为这个长 url 的短 url 地址

这种算法虽然会生成四个短链接,但是存在重复几率.

算法对比

采用自增序列的好处就是简单好理解易操作.但是由于id随着增大长度不固定,但是这个问题可以通过让id从指定的数字开始递增即可以解决.还有一个问题就是我们使用的短码是有序的,可能会存在安全方面的问题.当然相关的防护手法也有很多,比如签名验证之类的安全策略;我们也可以自己实现安全手法,比如从一个随机中心值进行开端计数,然后选用一些校检位算法计算出固定位的校检码,将其连接起来,得到固定长不递增的短码.

第二种算法存在碰撞的问题,虽然产生重复(碰撞)的几率很小.但是也采用这种算法也有一个好处就是短码的位数是固定的,不会从一位到多位.

所以这两种算法各有千秋,如果事务所需要的短链接有效期较短,那么通过批处理定期清洗,那么用摘要算法也不错.而自增算法能够确保任何恳求量都不会呈现冲突也不失一种非常好的解决算法.

重定向的问题(301还是302)

短链接重定向的执行过程:

用户访问短链接:https://dwz.cn/9WnR9Qcx

短链接服务器dwz.cn收到请求,根据URL路径9WnR9Qcx获取到原始的长链接:http://www.lishanlei.cn/

服务器返回状态码,将响应头中的Location设置为:http://www.lishanlei.cn/

浏览器重新向http://www.lishanlei.cn/发送请求

返回响应

Request URL: https://dwz.cn/9WnR9Qcx

Request Method: GET

Status Code: 302 Found

Remote Address: 220.181.164.108:443

Referrer Policy: no-referrer-when-downgrade

Access-Control-Allow-Credentials: true

Access-Control-Allow-Headers: Origin,Accept,Content-Type,X-Requested-With

Access-Control-Allow-Methods: POST,GET,PUT,PATCH,DELETE,HEAD

Access-Control-Allow-Origin:

Content-Length: 47

Content-Type: text/html; charset=utf-8

Date: Wed, 03 Oct 2018 05:42:18 GMT

Location: http://www.lishanlei.cn/

那么服务器在返回状态码时应该选取301还是302呢?

301是永久重定向,而302是临时重定向.

如果选取301,短链接生成以后就不会变化,所以用301符合http语义,这样对服务器的压力会有所减少.但是这样一来,我们就无法统计短地址被点击的次数了.

而选择302会增加服务器的压力,但是我们可以统计短链接被点击的次数,这些数据可能对于公司的发展规划非常重要.

综上所述,我认为更好的应该选择302

End~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,951评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,606评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,601评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,478评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,565评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,587评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,590评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,337评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,785评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,096评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,273评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,935评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,578评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,199评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,440评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,163评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,133评论 2 352

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,647评论 18 139
  • 文章图片上传不正常,如需文档,可联系微信:1017429387 目录 1 安装... 4 1.1 配置探针... ...
    Mrhappy_a7eb阅读 6,292评论 0 5
  • 还记得你2016年年初定下的目标吗? 还记得你当初写下的那么多的目标,现在来看看都实现了吗?有的人定完目标,第一...
    鹿伟伦阅读 428评论 0 0
  • 寒假阅读完好几本书,文章数却没有增加,只有硬逼自己写的《枢纽》笔记,我不禁为年度30篇文章的目标隐隐担忧,唯有不断...
    罗秋秋啾啾啾啾啾阅读 493评论 6 5
  • #能够认识你,真好# 不知多少次 暗中祷告 只为了心中的梦 不再飘渺 有一天 我们真的相遇了 万千欣喜 竟什么也说...
    八也阅读阅读 536评论 0 0