现在貌似TinyURL很火爆,也逐渐成为一种流行趋势。
对应于PHP版本的TinyURL也有一些算法,其实本质上来说是一种hash。
除此之外,还有另外一种TinyURL方案,类似于http://img.ly。
其实这种设计是最简单的,没有使用hash,而是递增,这种的好处就是数据库可以无限扩展,并且不会重复。
我们可以想想一下,我们只用大小写字母来表示,如果三位的话,就可以存储52*52*52=140608的URL,如果是4位的话就成了52*52*52*52=7311616,这个数量是几何级增长,并且搜索速度非常快。
PS:如果你觉得这不够用的话,你还可以把数字加进去:)
我刚才测试了下,我新建了一个表:
1
2
3
4
5
6
7
|
CREATE TABLE IF NOT EXISTS `url` (
`id` int(11) NOT NULL auto_increment,
`tiny` char(10) character set utf8 collate utf8_bin NOT NULL default '',
`url` text NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `tiny` (`tiny`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
|
注:使用utf8_bin是为了区分大小写。
然后我往表中添加了100w条数据,下面是我的算法,非常简单,还可以再优化:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
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);
}
}
|
从1开始,每个数字就可以生成一个唯一的标识符,然后插入到数据库中。
这时候我执行了一条SQL语句:
1
|
SELECT * FROM `url` WHERE tiny = 'DzPM'
|
在PHPMyAdmin中显示此条SQL执行耗费的时间是0.0003秒。
那如何运用在实际的项目中呢?
你可以每次执行插入SQL语句后,把返回的mysql_insert_id存到一个文件中,下次再读取一下,用这个数字来生成TinyURL。
当然,如果你有Memcached的话,直接放到这里面速度会更快。