基于Nginx+PHP+Redis的短URL系统的实现

一、所需环境

开发环境:CentOS 5.4

运行环境:Nginx+PHP+Redis

二、运行环境的部署

1、Nginx+PHP 环境的安装

参考:http://www.s135.com/nginx_php_v6

2、Redis 环境的安装
Redis服务端的安装

cd /usr/local/src/

#下载redis
wget http://redis.googlecode.com/files/redis-2.2.12.tar.gz

#解压
tar zxvf redis-2.2.12.tar.gz
cp -R redis-2.2.12 /usr/local/
mv /usr/local/redis-2.2.12/ /usr/local/redis
#可查看帮助文件 INSTALL
cd /usr/local/redis/src
make

#make命令执行完成后,会在src目录下生成5个可执行文件,分别是redis-server、redis-cli、redis-benchmark、redis-check-aof、redis-check-dump,它们的作用如下:
#redis-server:Redis服务器的daemon启动程序
#redis-cli:Redis命令行操作工具。当然,你也可以用telnet根据其纯文本协议来操作
#redis-benchmark:Redis性能测试工具,测试Redis在你的系统及你的配置下的读写性能
#redis-check-aof:更新日志检查
redis-check-dump:用于本地数据库检查

make install
#执行make install ,会执行如下的命令
mkdir -p /usr/local/bin
cp -p redis-server /usr/local/bin
cp -p redis-benchmark /usr/local/bin
cp -p redis-cli /usr/local/bin
cp -p redis-check-dump /usr/local/bin
cp -p redis-check-aof /usr/local/bin
#我习惯手动运行下面的命令:
cp /usr/local/redis/src/redis-server /usr/local/redis/
cp /usr/local/redis/src/redis-cli /usr/local/redis/
cp /usr/local/redis/src/redis-benchmark /usr/local/redis/

#配置redis.conf
根据实际情况来配置
#运行redis
/usr/local/redis/redis-server /usr/local/redis/redis.conf

phpredis模块的安装

#下载phpredis
wget https://nodeload.github.com/nicolasff/phpredis/tarball/master
tar zxvf nicolasff-phpredis-2.1.3-20-g9e1d068.tar.gz
mv nicolasff-phpredis-9e1d068/ phpredis
cd phpredis/
#生成扩展文件redis.so
/usr/local/webserver/php/bin/phpize
./configure –with-php-config=/usr/local/webserver/php/bin/php-config
make
make install

#make install 后会得到如下结果:
Installing shared extensions: /usr/local/webserver/php/lib/php/extensions/no-debug-non-zts-20060613/

接下来在php.ini中添加PHP的扩展目录(如果已添加则不用再次添加)

extension_dir = “/usr/local/webserver/php/lib/php/extensions/no-debug-non-zts-20060613/”

接着添加如下代码:

extension=redis.so

执行以下命令,即可看到加载的redis模块:

/usr/local/webserver/php/sbin/php-fpm reload

三、程序代码的实现

函数文件源码:

/*
 *common_function.php
 */

//短url 加密算法
function shortUrl($url, $salt = '') {
    $base62_units = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $base2_unit30 = (('0x' . substr(md5($url . $salt), 0, 8)) * 1) & 0x3fffffff;
    $base62_unit6 = '';
    while ($base2_unit30 > 0) {
        $base62_unit6 .= $base62_units[$base2_unit30 & 61];
        $base2_unit30 >>= 5;
    }
    return $base62_unit6;
}

//解析url
function parseUrl($url){
    $parse_url_arr = explode(':',($url));
    $url_pro_arr = array('http','https','ftp','svn');

    if(in_array(strtolower($parse_url_arr[0]),$url_pro_arr)){
        return $url;
    }else{
        return $url = 'http://'.$url;
    }
}

//获取短url方法
function getShortUrl($url){
        if(empty($url)) return false;

        $tmp_url = 'http://www.lamp100.cn/index.php?action=setUrl&url='.urlencode($url);
        // 1. 初始化
        $ch = curl_init();
        // 2. 设置选项,包括URL
        curl_setopt($ch, CURLOPT_URL, $tmp_url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_USERPWD, 'xikang:123456');
        curl_setopt($ch, CURLOPT_HEADER, 0);
        // 3. 执行并获取HTML文档内容
        $short_url = curl_exec($ch);
        // 4. 释放curl句柄
        curl_close($ch);

        return $short_url;
}

index.php 主入口文件:

header('Content-Type: text/html; charset=utf-8');
ini_set('display_errors',1);
include_once('common_function.php');

define('REDIS_HOST','127.0.0.1');
define('REDIS_PORT',6379);
define('AUTH_KEY','lamp100&^%$#@!');
define('PRE_URL','http://lamp100.cn/');
define('ERROR_URL','http://www.lamp100.com');
define('VERSION','v0.1:');
define('MAX_ID','MAX_ID:');
define('CHECKMD5','CHECKMD5:');

$redis = new Redis();
$redis->connect(REDIS_HOST,REDIS_PORT);

$action = trim($_GET['action']);
$url = trim($_GET['url']);
//解析url
$url = parseUrl($url);

$short_url = trim($_GET['short_url']);

if($action == 'setUrl'){
    //检测MD5表中是否有记录
    if(!$redis->get(CHECKMD5.md5($url))){
	//判断是否有最大值id
	$max_id = $redis->get(MAX_ID.'id');
	if(!$max_id){
	    $redis->set(MAX_ID.'id',10000);
	}else{

            //$url_key = shortUrl($url,AUTH_KEY);
            include_once('hex_conver.class.php');
            $hex = new Hex_conver();
	    $max_id = $max_id + 1;
            $redis->set(MAX_ID.'id',$max_id);
            $url_key =  $hex->hex10to62($max_id);
            $redis->set(VERSION.$url_key,$url);

	    //存储到md5表里
	    $redis->set(CHECKMD5.md5($url),$url_key);

	}
    }else{
	$url_key = $redis->get(CHECKMD5.md5($url));
    }

    echo '<a title="'.$url.'" href="'.$url.'" target="_blank">'.PRE_URL.$url_key.'</a>';

}elseif($action == 'getUrl'){
	if(empty($short_url)){
	    echo '请确认域名后面的字符串是否正确!';
	    exit;
	}

	$url_res = $redis->get(VERSION.$short_url);
	if($url_res){
	    echo '<a title="'.$url_res.'" href="'.$url_res.'" target="_blank">'.PRE_URL.$short_url.'</a>';
	}else{
	    echo '该短名称<
<span style="color: red;"> '.$short_url.' </span>还未被使用!';
	}

}elseif($action == 'redirect'){
        $url_res = $redis->get(VERSION.$short_url);
        if(!empty($url_res)){
            header('location:'. $url_res);
        }else{
	    header('location:'.ERROR_URL);
	}

}elseif($action == 'demo'){
 	$url = trim($_POST['url'])?trim($_POST['url']):$_GET['url'];
	if(!empty($url)){
		$short_url = getShortUrl($url);
	}else{
		$short_url = '';
	}
	include ('demo.php');

}else{
	echo '您请求的操作不存在';
	exit;
}

hex_conver.class.php 源码:

class Hex_conver{

	const KeyCode = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

	public function __construct(){

	}

	/**
	 * 将62进制的数字字符串转为10进制的数字字符串
	 * @param $m string 62进制的数字字符串
	 * @param $len integer 返回字符串长度,如果长度不够用0填充,0为不填充
	 * @return string
	 * @author
	 */
	public function hex62to10($m, $len = 0) {
		$m = (string)$m;
		$hex2 = '';
		$Code = self::KeyCode;
		for($i = 0, $l = strlen($Code); $i < $l; $i++) {
			$KeyCode[] = $Code[$i];
		}
		$KeyCode = array_flip($KeyCode);

		for($i = 0, $l = strlen($m); $i < $l; $i++) {
			$one = $m[$i];
			$hex2 .= str_pad(decbin($KeyCode[$one]), 6, '0', STR_PAD_LEFT);
		}
		$return = bindec($hex2);

		return $return;
	}

	/**
	 * 将10进制的数字字符串转为62进制的数字字符串
	 * @param $m string 10进制的数字字符串
	 * @param $len integer 返回字符串长度,如果长度不够用0填充,0为不填充
	 * @return string
	 * @author
	 */
	public function hex10to62($m, $len = 0) {
		$KeyCode = self::KeyCode;
		$hex2 = decbin($m);
		$hex2 = $this->str_rsplit($hex2, 6);
		$hex64 = array();
		foreach($hex2 as $one) {
			$t = bindec($one);
			$hex64[] = $KeyCode[$t];
		}
		$return = preg_replace('/^0*/', '', implode('', $hex64));
		if($len) {
			$clen = strlen($return);
			if($clen >= $len) {
				return $return;
			}
			else {
				return str_pad($return, $len, '0', STR_PAD_LEFT);
			}
		}
		return $return;
	}

	/**
	 * 功能和PHP原生函数str_split接近,只是从尾部开始计数切割
	 * @param $str string 需要切割的字符串
	 * @param $len integer 每段字符串的长度
	 * @return array
	 * @author
	 */
	protected function str_rsplit($str, $len = 1) {
                if($str == null || $str == false || $str == '') return false;
                $strlen = strlen($str);
                if($strlen <= $len) return array($str);
                $headlen = $strlen % $len;
                if($headlen == 0) {
                        return str_split($str, $len);
                }
                $return = array(substr($str, 0, $headlen));
                return array_merge($return, str_split(substr($str, $headlen), $len));
        }

四、实例运行


以上内容来自互联网,在此表示感谢!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值