短网址服务实现原理[run on Sina App Engine]

主要想介绍下类似新浪微博等各大网站的短链技术,其实网址缩短技术很有现实的价值,第一方面,可以节约服务器的存取程序,举个简单的例子,例如一个链接占30个字节,但是缩短后仅仅占10个字节,这对于高并发的站点就是一个不小的节约,另外一方面还可以增加页面的美观程度,那么这样的短链技术是怎么实现的呢?

其实原理很简单,就是假设每一个输入的链接为一个key,利用随即的字符串生成对应的六位数或者更长,根据数据的概率论,每一位可以十位数组+26个小写字母+26个大写的字母=62的可能性,这样随即生成六位就可以提供62的6次方,应该空间够大了。然后对每个网址对应一个value,也就是当前的nosql的技术key-value存取,这里不推荐mysql等传统的存取技术,第一个既然要用到生产的环境,那么网址缩短的技术就会很多,当mysql的表大到一定的程度的时候就会出现慢查询的情况,例如你的数据表达到1000万条记录,那么你再次select….where …等查询的时候就会遍历整个表,这是很费时的,对于生产环境是不合时宜的。但是当前的nosql技术就突破了这个技术瓶颈,根据sae官方提供的测试信息,key-value每秒的操作次数可以达到20W,但是我自己测试达不到这个次数,原因也很明显,那就是还需要通过httpd服务,这明显有一定的延迟,但是无论如何,还是大大的提高了效率。最后利用url rewrite技术对访问的短链提高header转跳,原理就是首先获取$yoururl/$yourshort 中的$short部分的内容,查询key-value nosql,返回对应key的value,然后header(‘location:$yourgetvalue’);就可以实现短链,当然还需要一定的技术处理,可以留给读者去完善,例如对于相同的网址就会生成两个key,可以预判网址是不是已经生成过短链,这样就可以节约一部分的空间。我没有测试新浪微博的短链技术是不是实现了这个预判的机制。

以下是我现实的代码部分:

这里主要利用了sae本身提供的服务,yaml以及kvdb完成。效率还是不错的,demo的地址是http://redirect.sinaapp.com/
先贴出config.yaml的配置,其实就相当于apache的rewrite功能,在apache下或者nginx下可以用类似的效果替代。

---
name: your app
version: 1
...
handle:
#URL重写
- rewrite:  if( !is_file() && !is_dir()) goto "redirect.php?id=%{QUERY_STRING}"

基本的实现也很简单,

index.php见代码包

redirect.php

<?php
$URL = $_SERVER['REQUEST_URI'];
//屏蔽第一位的/
$URL = substr($URL,1);
$kv = new SaeKVClient();
// 初始化KVClient对象
$ret = $kv->init();      
// 更新key-value
$ret = $kv->set('abc', 'http://baidu.com');
//var_dump($ret);
       
// 获得key-value
$ret = $kv->get($URL);
header("Location: $ret");//redirect
?>

代码打包下载:点击下载,有兴趣的朋友还可以写成api的形式,在其他的网站调用。