设计的主要问题,如何把一个url转成一个6位的字符串,且这些字符串不允许冲突,比如不能让两个不同的url生成同一个字符串
有的同学可能说直接md5然后截前6位,但是这样很容出现冲突
可能有的同学说用一个index来累加,但是6位的只能表达999999个链接,明显达不到要求,怎么办呢,笔者这里给一个思路
既然是6位,那么每位如果可能出现 0-9 a-z A-Z 就有 62的6次方种可能这样能表达的最大值就是ZZZZZZ换算成十进制就是56800235584这么多,够用啦,如果到时候还是不够,那咱们就升阶到7位,永远不用愁,其实咱们这里就是设计了一个62进制的数,算法实现如下
<?php
function get_key_from_index($index) {
$char_list = ['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',
'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'];
if($index==0) {
return 0;
}
if($index<=count($char_list)) {
return $char_list[$index-1];
}
$result = '';
while(true){
$remain = $index%62;
$result = get_key_from_index($remain).$result;
$index = intval($index/62);
if($index<62) {
$result = get_key_from_index($index).$result;
break;
}
}
return $result;
}
然后我们就需要一个计数器,这里简单选redis
function get_short_key(){
#$index = $redis->incr('short_url_index');
$key = get_key_from_index(1000);
echo sprintf("%06s",$key);
}
echo get_short_key();
生成短链接key大功告成,记得存到mysql的时候编码选utf8_bin,如果选了utf8_gen_ci这个不会区分大小写,注意喽
第二步,我们的最终目标是http://域名/a0Z3d4 这种格式,这种直接访问就404,所有我们的nginx需要配一下
在nginx的域名配置模块中加入代码
server {
listen 80;
server_name t.cn;
index index.html index.htm index.php;
root /Users/www/rsf/app-web;
#注意这里是关键,所有请求转发到index.php
rewrite . /index.php;
location ~ .*\.(php|php5)?$ {
fastcgi_pass unix:/tmp/php-cgi.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
然后我们在index.php中获取request_uri就可以得到这个字符串了
这种代码就不用贴了吧
over