MongoDB安装

wget -c  http://fastdl.mongodb.org/linux/mongodb-linux-i686-2.4.1.tgz
tar zxvf mongodb-src-r2.4.1.tar.gz
mv mongodb-linux-i686-2.4.1 /usr/local/mongodb/
/usr/local/mongodb/bin/mongod --dbpath=/usr/local/mongodb/data/ --logpath=/usr/local/mongodb/dblogs --fork</pre>

启动以后可以查看mongodb进程树

pstree -p |grep mongod

PHP MongoDB 扩展

wget http://pecl.php.net/get/mongo-1.3.6.tgz
/usr/bin/phpize
./configure --with-php-config=/usr/local/php/bin/php-config
make && make install
/usr/local/php/etc/php.ini
extension=mongo.so;

关闭注意 这里禁止使用 kill -9 PID 关闭mongodb进程,会导致mongod.lock导致再一次无法开启mongodb,必须删除mongod.lock再能开启
可以使用pkill mongod 或者 killall mongod 来结束mongodb进程

快速安装, 到Nodejs官网下载最新的安装包。

wget http://nodejs.org/dist/v0.9.0/node-v0.9.0.tar.gz
tar zxvf node-v0.9.0.tar.gz

cd node-v0.9.0
./configure --prefix=/usr/local/node
make && make install

vi /etc/profile 
#安装完成后,配置环境变量
#export PATH USER上面添加
#set for nodejs 
export NODE_HOME=/usr/local/node
export PATH=$NODE_HOME/bin:$PATH

#保存退出,使刚才的配置生效 
source /etc/profile

老规矩,创建一个server.js来完成hello world!

var http = require('http');
http.createServer(function (request, response) {
    console.log("Request received.");
    response.writeHead(200, {'Content-Type': 'text/plain'});
    response.write('Hello World');
    response.end();
}).listen(8888);
console.log('Server running.');

开启服务

node server.js

会看到Linux控制台上打印出Server running.
我们再用浏览器访问下:http://192.168.1.102:8888/

浏览器上打印出:

Hello World

而Linux控制台上出现两次

Request received.  
Request received.  

出现两次请求信息是因为大部分服务器访问你的http://192.168.1.102:8888/时会读取http://192.168.1.102:8888/favicon.ico导致的。

本文转自:基于HTTP协议的轻量级开源简单队列服务

最近因为工作需要才解除到队列服务,不可不说HTTPSQS是个非常高效的一个服务应用。

先介绍一些队列的原理和应用:

队列(Queue)又称先进先出表(First In First Out),即先进入队列的元素,先从队列中取出。加入元素的一头叫“队头”,取出元素的一头叫“队尾”。利用消息队列可以很好地异步处理数据传送和存储,当你频繁地向数据库中插入数据、频繁地向搜索引擎提交数据,就可采取消息队列来异步插入。另外,还可以将较慢的处理逻辑、有并发数量限制的处理逻辑,通过消息队列放在后台处理,例如FLV视频转换、发送手机短信、发送电子邮件等。

HTTPSQS(HTTP Simple Queue Service)是一款基于 HTTP GET/POST 协议的轻量级开源简单消息队列服务,使用 Tokyo Cabinet 的 B+Tree Key/Value 数据库来做数据的持久化存储。

项目网址:http://code.google.com/p/httpsqs/
使用文档:http://zyan.cc/httpsqs/
使用环境:Linux(同时支持32位、64位操作系统,推荐使用64位操作系统)

服务器安装

wget http://httpsqs.googlecode.com/files/libevent-2.0.12-stable.tar.gz
tar zxvf libevent-2.0.12-stable.tar.gz
cd libevent-2.0.12-stable/
./configure --prefix=/usr/local/libevent-2.0.12-stable/
make && make install
cd ../

wget http://httpsqs.googlecode.com/files/tokyocabinet-1.4.47.tar.gz
tar zxvf tokyocabinet-1.4.47.tar.gz
cd tokyocabinet-1.4.47/
./configure --prefix=/usr/local/tokyocabinet-1.4.47/
#Note: In the 32-bit Linux operating system, compiler Tokyo cabinet, please use the ./configure --enable-off64 instead of ./configure to breakthrough the filesize limit of 2GB.
#./configure --enable-off64 --prefix=/usr/local/tokyocabinet-1.4.47/
make && make install
cd ../

wget http://httpsqs.googlecode.com/files/httpsqs-1.7.tar.gz
tar zxvf httpsqs-1.7.tar.gz
cd httpsqs-1.7/
make && make install
cd ../

这里注意安装第二个tokyocabinet的时候如果是64位系统请按照注释出使用配置文件,不清楚是多少位可以用:

getconf LONG_BIT
#或者
getconf WORD_BIT
#或者
file /bin/ls

安装好后,执行httpsqs -h能看到一系列帮助参数信息。

httpsqs -h

创建data,设置端口为1218

httpsqs -d -p 1218 -x /data0/queue

访问你的URL,如

http://192.168.1.102:1218/?name=your_queue_name&amp;opt=put&amp;data=my_data

看到浏览器上出现HTTPSQS_PUT_OK,表示队列写入成功
访问URL

http://192.168.1.102:1218/?name=your_queue_name&opt=get

看到浏览器上出现my_data,表示取出your_queue_name一个数据my_data
再次刷新发现出现HTTPSQS_GET_END,表示队列中已经没有数据了。

本文译自:Create Youtube-like IDs with PHP/Python/Javascript/Java/SQL

id通常都是用数字,不巧的是只有10个数字来使用,所以如果你有很多的记录,id往往变得非常冗长。当然对于计算机来说无所谓,但我们更希望id尽可能短。所以我们如何能使id变短?我们可以利用字母让它们附加上数字。字母可以解决!

所以这里就有两个问题:

  • 如何使用PHP和MySQL创建独特的短字符串id?
  • 或如何创建id类似YouTube的方式,如yzNjIBEdyww?

我很久以前创建了这个函数。是时候和大家分享一下了。

多就是少 – “这就是数学”

字母有26个字母。这是一个已经超过10字数。如果我们还区分大写和小写字母,并添加数字,我们已经有(26 x 2 + 10)=62个选项我们可以使用,让它出现在我们的id中。

当然我们现在也可以添加其他特殊字符如:/ * & #,但是那些可能导致的URL上的一些问题。

因为大约有60+字符,让id变的更短,所以我们有更多的选择可以使数据在每个位置。

这就是因为网址必须做的更加短,就像youtube上看到的:http://www.youtube.com/watch?v=yzNjIBEdyww

转化你的id

不同于数据库服务器,网络服务容易收录这样的字符,这样你就可以让做一个转换id和字符串,同时保持你的数据库的快速与数字(MySQL真正喜欢它们纯数字);

由此产生的字符串不是很难破译, 但它可以是一个非常不错的功能使url或目录结构更紧凑的和更重要。

所以基本上:

  • 当有人请求rLHWfKd
  • alphaID()将其转换为999999999999
  • 你查找的记录id 999999999999在你的数据库

PHP方式

/**
 * Translates a number to a short alhanumeric version
 *
 * Translated any number up to 9007199254740992
 * to a shorter version in letters e.g.:
 * 9007199254740989 --> PpQXn7COf
 *
 * specifiying the second argument true, it will
 * translate back e.g.:
 * PpQXn7COf --> 9007199254740989
 *
 * this function is based on any2dec && dec2any by
 * fragmer[at]mail[dot]ru
 * see: http://nl3.php.net/manual/en/function.base-convert.php#52450
 *
 * If you want the alphaID to be at least 3 letter long, use the
 * $pad_up = 3 argument
 *
 * In most cases this is better than totally random ID generators
 * because this can easily avoid duplicate ID's.
 * For example if you correlate the alpha ID to an auto incrementing ID
 * in your database, you're done.
 *
 * The reverse is done because it makes it slightly more cryptic,
 * but it also makes it easier to spread lots of IDs in different
 * directories on your filesystem. Example:
 * $part1 = substr($alpha_id,0,1);
 * $part2 = substr($alpha_id,1,1);
 * $part3 = substr($alpha_id,2,strlen($alpha_id));
 * $destindir = "/".$part1."/".$part2."/".$part3;
 * // by reversing, directories are more evenly spread out. The
 * // first 26 directories already occupy 26 main levels
 *
 * more info on limitation:
 * - http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/165372
 *
 * if you really need this for bigger numbers you probably have to look
 * at things like: http://theserverpages.com/php/manual/en/ref.bc.php
 * or: http://theserverpages.com/php/manual/en/ref.gmp.php
 * but I haven't really dugg into this. If you have more info on those
 * matters feel free to leave a comment.
 *
 * The following code block can be utilized by PEAR's Testing_DocTest
 * <code>
 * // Input //
 * $number_in = 2188847690240;
 * $alpha_in  = "SpQXn7Cb";
 *
 * // Execute //
 * $alpha_out  = alphaID($number_in, false, 8);
 * $number_out = alphaID($alpha_in, true, 8);
 *
 * if ($number_in != $number_out) {
 *    echo "Conversion failure, ".$alpha_in." returns ".$number_out." instead of the ";
 *    echo "desired: ".$number_in."\n";
 * }
 * if ($alpha_in != $alpha_out) {
 *    echo "Conversion failure, ".$number_in." returns ".$alpha_out." instead of the ";
 *    echo "desired: ".$alpha_in."\n";
 * }
 *
 * // Show //
 * echo $number_out." => ".$alpha_out."\n";
 * echo $alpha_in." => ".$number_out."\n";
 * echo alphaID(238328, false)." => ".alphaID(alphaID(238328, false), true)."\n";
 *
 * // expects:
 * // 2188847690240 => SpQXn7Cb
 * // SpQXn7Cb => 2188847690240
 * // aaab => 238328
 *
 * </code>
 *
 * @author   Kevin van Zonneveld <[email protected]>
 * @author   Simon Franz
 * @author   Deadfish
 * @copyright 2008 Kevin van Zonneveld (http://kevin.vanzonneveld.net)
 * @license   http://www.opensource.org/licenses/bsd-license.php New BSD Licence
 * @version   SVN: Release: $Id: alphaID.inc.php 344 2009-06-10 17:43:59Z kevin $
 * @link   http://kevin.vanzonneveld.net/
 *
 * @param mixed   $in      String or long input to translate
 * @param boolean $to_num  Reverses translation when true
 * @param mixed   $pad_up  Number or boolean padds the result up to a specified length
 * @param string  $passKey Supplying a password makes it harder to calculate the original ID
 *
 * @return mixed string or long
 */
function alphaID($in, $to_num = false, $pad_up = false, $pass_key = null)
{
    $out   =   '';
    $index = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $base  = strlen($index);

    if ($pass_key !== null) {
        // Although this function's purpose is to just make the
        // ID short - and not so much secure,
        // with this patch by Simon Franz (http://blog.snaky.org/)
        // you can optionally supply a password to make it harder
        // to calculate the corresponding numeric ID

        for ($n = 0; $n < strlen($index); $n++) {
            $i[] = substr($index, $n, 1);
        }

        $pass_hash = hash('sha256',$pass_key);
        $pass_hash = (strlen($pass_hash) < strlen($index) ? hash('sha512', $pass_key) : $pass_hash);

        for ($n = 0; $n < strlen($index); $n++) {
            $p[] =  substr($pass_hash, $n, 1);
        }

        array_multisort($p, SORT_DESC, $i);
        $index = implode($i);
    }

    if ($to_num) {
        // Digital number  <<--  alphabet letter code
        $len = strlen($in) - 1;

        for ($t = $len; $t >= 0; $t--) {
            $bcp = bcpow($base, $len - $t);
            $out = $out + strpos($index, substr($in, $t, 1)) * $bcp;
        }

        if (is_numeric($pad_up)) {
            $pad_up--;

            if ($pad_up > 0) {
                $out -= pow($base, $pad_up);
            }
        }
    } else {
        // Digital number  -->>  alphabet letter code
        if (is_numeric($pad_up)) {
            $pad_up--;

            if ($pad_up > 0) {
                $in += pow($base, $pad_up);
            }
        }

        for ($t = ($in != 0 ? floor(log($in, $base)) : 0); $t >= 0; $t--) {
            $bcp = bcpow($base, $t);
            $a   = floor($in / $bcp) % $base;
            $out = $out . substr($index, $a, 1);
            $in  = $in - ($a * $bcp);
        }
    }

    return $out;
}

还有一个可选的第三个参数:$pad_up。这能使生成的alphaId至少X字符长。
你可以支持更多字符(使生成的alphaID甚至更小)通过添加和修改函数顶部的$index变量。

Javascript方式

/**
 *  Javascript AlphabeticID class
 *  (based on a script by Kevin van Zonneveld <[email protected]>)
 *
 *  Author: Even Simon <[email protected]>
 *
 *  Description: Translates a numeric identifier into a short string and backwords.
 *
 *  Usage:
 *    var str = AlphabeticID.encode(9007199254740989); // str = 'fE2XnNGpF'
 *    var id = AlphabeticID.decode('fE2XnNGpF'); // id = 9007199254740989;
 **/

var AlphabeticID = {
    index:'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ',

    /**
     *  [@function](http://twitter.com/function) AlphabeticID.encode
     *  [@description](http://twitter.com/description) Encode a number into short string
     *  [@param](http://twitter.com/param) integer
     *  [@return](http://twitter.com/return) string
     **/
    encode:function(_number){
        if('undefined' == typeof _number){
            return null;
        } else if('number' != typeof(_number)){
            throw new Error('Wrong parameter type');
        }

        var ret = '';

        for(var i=Math.floor(Math.log(parseInt(_number))/Math.log(AlphabeticID.index.length));i>=0;i--){
            ret = ret + AlphabeticID.index.substr((Math.floor(parseInt(_number) / AlphabeticID.bcpow(AlphabeticID.index.length, i)) % AlphabeticID.index.length),1);
        }

        return ret.reverse();
    },

    /**
     *  [@function](http://twitter.com/function) AlphabeticID.decode
     *  [@description](http://twitter.com/description) Decode a short string and return number
     *  [@param](http://twitter.com/param) string
     *  [@return](http://twitter.com/return) integer
     **/
    decode:function(_string){
        if('undefined' == typeof _string){
            return null;
        } else if('string' != typeof _string){
            throw new Error('Wrong parameter type');
        }

        var str = _string.reverse();
        var ret = 0;

        for(var i=0;i<=(str.length - 1);i++){
            ret = ret + AlphabeticID.index.indexOf(str.substr(i,1)) * (AlphabeticID.bcpow(AlphabeticID.index.length, (str.length - 1) - i));
        }

        return ret;
    },

    /**
     *  [@function](http://twitter.com/function) AlphabeticID.bcpow
     *  [@description](http://twitter.com/description) Raise _a to the power _b
     *  [@param](http://twitter.com/param) float _a
     *  [@param](http://twitter.com/param) integer _b
     *  [@return](http://twitter.com/return) string
     **/
    bcpow:function(_a, _b){
        return Math.floor(Math.pow(parseFloat(_a), parseInt(_b)));
    }
};

/**
 *  [@function](http://twitter.com/function) String.reverse
 *  [@description](http://twitter.com/description) Reverse a string
 *  [@return](http://twitter.com/return) string
 **/
String.prototype.reverse = function(){
    return this.split('').reverse().join('');
};

其他语言请参照原文:
http://kvz.io/blog/2009/06/10/create-short-ids-with-php-like-youtube-or-tinyurl/

我们知道当插入多条数据的时候insert支持多条语句:

INSERT INTO t_member (id, name, email) VALUES
    (1, 'nick', '[email protected]'),
    (4, 'angel','[email protected]'),
    (7, 'brank','[email protected]');

但是对于更新记录,由于update语法不支持一次更新多条记录,只能一条一条执行:

UPDATE t_member SET name='nick', email='[email protected]' WHERE id=1;
UPDATE t_member SET name='angel', email='[email protected]' WHERE id=4;
UPDATE t_member SET name='brank', email='[email protected]' WHERE id=7;

这里问题就出现了,倘若这个update list非常大时(譬如说5000条),这个执行率可想而知。

这就要介绍一下在MySql中INSERT语法具有一个条件DUPLICATE KEY UPDATE,这个语法和适合用在需要判断记录是否存在,不存在则插入存在则更新的记录。

具体的语法可以参见:http://dev.mysql.com/doc/refman/5.0/en/insert.html

基于上面这种情况,针对更新记录,仍然使用insert语句,不过限制主键重复时,更新字段。如下:

INSERT INTO t_member (id, name, email) VALUES
    (1, 'nick', '[email protected]'),
    (4, 'angel','[email protected]'),
    (7, 'brank','[email protected]')
ON DUPLICATE KEY UPDATE name=VALUES(name), email=VALUES(email);

注意:ON DUPLICATE KEY UPDATE只是MySQL的特有语法,并不是SQL标准语法!