短网址服务的原理是什么?

  针对于有些用户担心短网址会不会重复的问题,我们将短网址服务的原理进行了详细介绍,以便用户对短网址有更深的理解,消除其担心。

  Q:那么小的长度应该有一定概率会重复的吧?是不是一定时间后就不可用了?

  A:  短网址(Short URL),顾名思义就是在形式上比较短的网址。通常用的是asp或者php转向,在Web 2.0的今天,不得不说,这是一个潮流。目前已经有许多类似服务,借助短网址您可以用简短的网址替代原来冗长的网址,让使用者可以更容易的分享链接。

  例如:http://t.cn/SzjPjA

  短网址服务,可能很多朋友都已经不再陌生,现在大部分微博、手机邮件提醒等地方已经有很多应用模式了,并占据了一定的市场。估计很多朋友现在也正在使用。

  看过新浪的短连接服务,发现后面主要有6个字符串组成,于是第一个想到的就是原来公司写的一个游戏激活码规则,也就是下面的算法2,

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

  自从twitter推出短网址(shorturl),继之国内各大微博跟风,google公开goo.gl使用API,短网址之风愈演愈烈.不得不说这是一个新兴又一大热门web2.0服务.现整理一下,包括完整短网址网站,短网址生成原理,算法举例,以及优劣比较。

  短链接的好处:

  1、内容需要;2、用户友好;3、便于管理。

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

  微博限制字数为140字一条,那么如果我们需要发一些连接上去,但是这个连接非常的长,以至于将近要占用我们内容的一半篇幅,这肯定是不能被允许的,所以短网址应运而生了。

  短网址可以在我们项目里可以很好的对开放级URL进行管理。有一部分网址可以会涵盖暴力,广告等信息,这样我们可以通过用户的举报,完全管理这个连接将不出现在我们的应用中,应为同样的URL通过加密算法之后,得到的地址是一样的。

  我们可以对一系列的网址进行流量,点击等统计,挖掘出大多数用户的关注点,这样有利于我们对项目的后续工作更好的作出决策。

  算法原理

  算法一

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

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

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

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

  这种算法,虽然会生成4个,但是仍然存在重复几率,下面的算法一和三,就是这种的实现.

  算法二

  a-zA-Z0-9 这64位取6位组合,可产生500多亿个组合数量.把数字和字符组合做一定的映射,就可以产生唯一的字符串,如第62个组合就是aaaaa9,第63个组合就是aaaaba,再利用洗牌算法,把原字符串打乱后保存,那么对应位置的组合字符串就会是无序的组合。

  把长网址存入数据库,取返回的id,找出对应的字符串,例如返回ID为1,那么对应上面的字符串组合就是bbb,同理 ID为2时,字符串组合为bba,依次类推,直至到达64种组合后才会出现重复的可能,所以如果用上面的62个字符,任意取6个字符组合成字符串的话,你的数据存量达到500多亿后才会出现重复的可能。

  具体参看这里彻底完善新浪微博接口和超短URL算法,算法四可以算作是此算法的一种实现,此算法一般不会重复,但是如果是统计的话,就有很大问题,特别是对域名相关的统计,就抓瞎了。

  JAVA 实现代码:

  public class ShortUrlGenerator {

  /**

  * @param args

  */

  public static void main(String[] args) {

  String sLongUrl = "QQ空间"; //长链接

  String[] aResult = shortUrl(sLongUrl);

  // 打印出结果

  for (int i = 0; i < aResult.length; i++) {

  System.out.println("[" + i + "]:::" + aResult[i]);

  }

  }

  public static String[] shortUrl(String url) {

  // 可以自定义生成 MD5 加密字符传前的混合 KEY

  String key = "mengdelong";

  // 要使用生成 URL 的字符

  String[] chars = new String[]{"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", "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"

  };

  // 对传入网址进行 MD5 加密

  String sMD5EncryptResult = (new Encrypt()).md5(key + url);

  String hex = sMD5EncryptResult;

  String[] resUrl = new String[4];

  for (int i = 0; i < 4; i++) {

  // 把加密字符按照 8 位一组 16 进制与 0x3FFFFFFF 进行位与运算

  String sTempSubString = hex.substring(i * 8, i * 8 + 8);

  // 这里需要使用 long 型来转换,因为 Inteper .parseInt() 只能处理 31 位 , 首位为符号位 , 如果不用 long ,则会越界

  long lHexLong = 0x3FFFFFFF & Long.parseLong(sTempSubString, 16);

  String outChars = "";

  for (int j = 0; j < 6; j++) {

  // 把得到的值与 0x0000003D 进行位与运算,取得字符数组 chars 索引

  long index = 0x0000003D & lHexLong;

  // 把取得的字符相加

  outChars += chars[(int) index];

  // 每次循环按位右移 5 位

  lHexLong = lHexLong >> 5;

  }

  // 把字符串存入对应索引的输出数组

  resUrl[i] = outChars;

  }

  return resUrl;

  }

  }