• 〖杂七杂八〗-- 短URL链接系统


    【短URL链接系统】

    定义:  

      短网址(Short URL),顾名思义就是在形式上比较短的网址。但不知道有多少人像我一样,由于面试问道才知道有这种系统而对短连接原理好奇,从而进行进一步的研究。在Web 2.0的今天,不得不说,这是一个潮流。目前已经有许多类似服务(短网址服务,现在大部分微博、手机邮件提醒等地方已经有很多应用模式了,并占据了一定的市场),借助短网址您可以用简短的网址替代原来冗长的网址,让使用者可以更容易的分享链接。例如:http://t.cn/SzjPjA。

      自从twitter推出短网址(shorturl),继之国内各大微博跟风,google公开goo.gl使用API,短网址之风愈演愈烈。不得不说这是一个新兴又一大热门web2.0服务。

    为什么要这样做的,原因我想有这样几点:

      1、微博限制字数为140字一条,那么如果我们需要发一些连接上去,但是这个连接非常的长,以至于将近要占用我们内容的一半篇幅,这肯定是不能被允许的,所以短网址应运而生了。
      2、短网址可以在我们项目里可以很好的对开放级URL进行管理。有一部分网址可以会涵盖暴力,广告等信息,这样我们可以通过用户的举报,完全管理这个连接将不出现在我们的应用中,应为同样的URL通过加密算法之后,得到的地址是一样的。
      3、我们可以对一系列的网址进行流量,点击等统计,挖掘出大多数用户的关注点,这样有利于我们对项目的后续工作更好的作出决策。

    短连接构成:

      协议+域名+参数

      例如:http://t.cn/SzjPjA 主要是参数:SzjPjA。这个是唯一标识。

    短链接的好处:

      1、内容需要;

      2、用户友好;

      3、便于管理。

    短连接用途:

      最简单的用途就是他的名字直译“短”的“链接”,可以把长长的一串链接(例如:亚马逊的购买链接)缩短成为几个简单的字符。

    短连接原理:

      短连接原理非常简单,就是用户访问短连接地址,到达我们的短连接网站,然后网站通过短连接里的code,查询数据库得到原始url,然后让网页跳转到原始url即可。

      1、针对小型应用:
        1)通过发号策略,给每一个过来的长地址,发一个号即可,小型系统直接用mysql的自增索引就搞定了。
        2)创建一张数据库表,仅需要有2列即可:code列和url列。code列也就是标识列,建议直接设置为自增主键。用于存储短连接参数代码,也就是短连接里的code。

      url列用于存储要跳转的原始url。

      2、针对大型应用:
        可以考虑各种分布式key-value系统做发号器。不停的自增就行了。第一个使用这个服务的人得到的短地址是http://xx.xx/0 第二个是 http://xx.xx/1 第11个是 http://xx.xx/a

       依次往后,相当于实现了一个自增字段即可。

      所说的链接推广分析功能,就是在这个过程中,记录访客的某些信息,例如:访问时间、访问的短链接、访客的IP、访客的UserAgent信息等。基于这些信息,配合推广方式,就可以辅助判断出什么时间,什么范围,什么人群的推广更有曝光效果。

    短链接实现方法:

    面试时,我的回答:
      1、小型的就用数据库就好,利用自增ID作为参数;
      2、大型的也就是高并发的情况,使用redis这种k-v存储系统进行存储。我的思路如下:利用列表存储,每个列表存储1万个数据;redis中每个列表的key从1开始(也就是对1万做整除);如果想得到某个短链接对应的原地址,那就通过divmod函数进行计算,他的商就代表是第几个列表,余数代表他的位置。这样去获取。
      3、如果使用redis去实现的化,怎么保证你的系统内存不被撑爆?就是说我上一种存储机制是完全把数据存放在内存中的!我当时的回答是每隔一段时间做一次持久化。
      4、内存的问题解决了,但是如果过一段时间我再来获取我存放的原url地址(假如我做持久化的时间是每隔12个小时,原数据已经存放到数据库中),这种情况怎么解决?我当时的回答是从数据表(表结构的设计是:原url,还有个num列)中批量获取一段数据,放入redis(但是这样的话就没有考虑高访问的情况,相当于是又把内存撑爆了)。

      5、并发的问题。

    网上查找得到的解决方案:(由简入难)

    第一种:
      26个大写字母 26小写字母,10个数字,随机生成6个然后插入数据库对应一个id,短连接跳转的时候,根据字符串查询到对应id,即可实现相应的跳转!不过2的62次方,不知道有没有重复的,小概率可以,但是对应不是很大的网站应该足够了。

    第二种:
      通过发号策略进行存储
    几个子问题:
    1、如何用数据库或者KV存储来做? 
      用10进制去记录。比如第10000个长地址,我们给它的短地址对应的编号是9999,我们通过存储自增拿到9999后,作为参数加到短链接之后;另一种方式就是拿到这个数之后,再做一个进制转换,例如10进制转成16进制(晋级版的可以考虑加密)。

    2、如何实现同一个长地址多次转换,出来还是同一个短地址?
      上面的发号原理中,是不判断长地址是否已经转过的。也就是说用拿着百度首页地址来转,我给一个http://xx.xx/abc 过一段时间你再来转,我还会给你一个 http://xx.xx/xyz。这看起来挺不好的,但是不好在哪里呢?不好在不是一一对应,而一长对多短。这与我们完美主义的基因不符合,那么除此以外还有什么不对的地方? 
      有人说它浪费空间,这是对的。同一个长地址,产生多条短地址记录,这明显是浪费空间的。那么我们如何避免空间浪费,有人非常迅速的回答我,建立一个长对短的KV存储即可。嗯,听起来有理,但是。。。这个KV存储本身就是浪费大量空间。所以我们是在用空间换空间,而且貌似是在用大空间换小空间。真的划算吗?这个问题要考虑一下。当然,也不是没有办法解决,我们做不到真正的一一对应,那么打个折扣是不是可以搞定?
      这个方案最简单的是建立一个长对短的hashtable,这样相当于用空间来换空间,同时换取一个设计上的优雅(真正的一对一)。而实际情况是有很多性价比高的打折方案可以用。我的方案是:用key-value存储,保存“最近”生成的长对短的一个对应关系。注意是“最近”,也就是说,我并不保存全量的长对短的关系,而只保存最近的。比如采用一小时过期的机制来实现LRU淘汰。

    这样的话,长转短的流程变成这样: 
      1.0 在这个“最近”表中查看一下,看长地址有没有对应的短地址 
      1.1 有就直接返回,并且将这个key-value对的过期时间再延长成一小时 
      1.2 如果没有,就通过发号器生成一个短地址,并且将这个“最近”表中,过期时间为1小时
      所以当一个地址被频繁使用,那么它会一直在这个key-value表中,总能返回当初生成那个短地址,不会出现重复的问题。如果它使用并不频繁,那么长对短的key会过期,LRU机制自动就会淘汰掉它。
      当然,这不能保证100%的同一个长地址一定能转出同一个短地址,比如你拿一个生僻的url,每间隔1小时来转一次,你会得到不同的短地址。这样做对整个短系统是没有影响的。

    3、如何保证发号器的大并发高可用?
      上面设计看起来有一个单点,那就是发号器。如果做成分布式的,那么多节点要保持同步加1,多点同时写入,这个嘛,以CAP理论看,是不可能真正做到的。其实这个问题的解决非常简单,我们可以退一步考虑,我们是否可以实现两个发号器,一个发单号,一个发双号,这样就变单点为多点了?依次类推,我们可以实现1000个逻辑发号器,分别发尾号为0到999的号。每发一个号,每个发号器加1000,而不是加1。这些发号器独立工作,互不干扰即可。而且在实现上,也可以先是逻辑的,真的压力变大了,再拆分成独立的物理机器单元。1000个节点,估计对人类来说应该够用了。如果你真的还想更多,理论上也是可以的。

    4、具体存储如何选择?
      这个问题就不展开说了,各有各道,主要考察的是对存储的理解。对缓存原理的理解,和对市面上DB、Cache系统可用性,并发能力,一致性等方面的理解。

    5、跳转用301还是302?
      这也是一个有意思的话题。首先当然考察一个候选人对301和302的理解。浏览器缓存机制的理解。然后是考察他的业务经验。301是永久重定向,302是临时重定向。短地址一经生成就不会变化,所以用301是符合http语义的。同时对服务器压力也会有一定减少。 
      但是如果使用了301,我们就无法统计到短地址被点击的次数了。而这个点击次数是一个非常有意思的大数据分析数据源。能够分析出的东西非常非常多。所以选择302虽然会增加服务器压力,但是我想是一个更好的选择。

  • 相关阅读:
    golang 数据结构 优先队列(堆)
    leetcode刷题笔记5210题 球会落何处
    leetcode刷题笔记5638题 吃苹果的最大数目
    leetcode刷题笔记5637题 判断字符串的两半是否相似
    剑指 Offer 28. 对称的二叉树
    剑指 Offer 27. 二叉树的镜像
    剑指 Offer 26. 树的子结构
    剑指 Offer 25. 合并两个排序的链表
    剑指 Offer 24. 反转链表
    剑指 Offer 22. 链表中倒数第k个节点
  • 原文地址:https://www.cnblogs.com/SHENGXIN/p/8080129.html
Copyright © 2020-2023  润新知