前言

  随着twitter的流行,tinyURL的方式也变得流行起来。简单的说,tinyURL就是将一个很长的url通过某种hash算法,对应到一个很短的url,然后复制或者

使用时就可以用这个简短的url了,参看tinyurl.com 例如http://www.yaronspace.cn/blog/index.php/archives/572 这个链接,使用tinyURL服务可以将其转化

http://tinyurl.com/2bejtdo 这样用起来就非常地方便了

原理

  其实实现tinyURL这种功能不是很难,相当于再访问http://tinyurl.com/2bejtdo 这个链接时,tinyurl.com首先会找到2bejtdo对应的原始
URL链接,然后进行重定向到原始的URL即可。涉及以下两个问题:

  第一,tinyURL 与 原始的URL如何进行对应,也就是说如何通过原始的URL计算获得一个全局唯一的tinyURL,并且保证这个tinyURL尽可能地短;

  第二,tinyURL 与 原始的URL如何保存,如何能够高效地在已知tinyURL的情况下能够查询获得原始的URL;

设计方案

  第一种方案:不适用hash函数,采用递增的方式,存在一个全局的ID,每新来一个url,将ID加一,将将这个ID作为原始URL的全局标识,然后由这个ID生成对应的tinyURL
  优点:可以无限扩展,并且不会重复
  缺点:如何保存全局ID,如果保存到文件中,在高并发情况下这个将成为系统瓶颈所在,当然也可保存在memcache中。
由对应ID生成tinyURL的方法

function getTinyUrl($num) {
	$alpha = array_merge(range(65, 90), range(97, 122));
	if($num < 52) {
		return chr($alpha[$num]);
	} else {
		$tiny = chr($alpha[$num%52]);
		while(($num = (int)($num/52)) >= 1) {
			if($num<=52) {
				$tiny .= chr($alpha[$num-1]);
			} else {
				$tiny .= chr($alpha[$num%52]);
			}
		}
		return strrev($tiny);
	}
}

  第二种方案:使用某种hash函数,将原始的URL转化为64位的int整数,然后再对这个64位int整数,利用上述方法将其转化为由字母与数字组成的tinyURL

  如何存储tinyURl与原始的URL:存储到mysql表中

--
-- 表的结构 `tinyurl`
--
 
CREATE TABLE IF NOT EXISTS `tinyurl` (
  `tinyurl` VARCHAR(20) COLLATE utf8_bin NOT NULL,
  `longurl` text COLLATE utf8_bin NOT NULL,
  PRIMARY KEY (`tinyurl`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

tinyURL字段作为主键,通过tinyURL来查询时由于索引的存在,速度是可以接受的;同时在插入新的记录时,使用replace语句,而不是insert语句
这样就保证了在tinyURL已经存在的情况下,只会覆盖之前的记录,这是解决hash函数冲突的一种解决方法。

本文采用第二种解决方法
未完待续……
本文地址:http://www.yaronspace.cn/blog/index.php/archives/596