• 2009-11-20

    php引用符号(&)的作用 - [php]

    php的引用(就是在变量或者函数、对象等前面加上&符号)

    PHP 中引用的意思是:不同的名字访问同一个变量内容.
    与C语言中的指针是有差别的.C语言中的指针里面存储的是变量的内容在内存中存放的地址

    变量的引用

    PHP 的引用允许你用两个变量来指向同一个内容

    <?
    $a="ABC";
    $b =&$a;
    echo $a;//这里输出:ABC
    echo $b;//这里输出:ABC
    $b="EFG";
    echo $a;//这里$a的值变为EFG 所以输出EFG
    echo $b;//这里输出EFG
    ?>


    函数的传址调用
    传址调用我就不多说了 下面直接给出代码

    function test(&$a)
    {
    $a=$a+100;
    }
    $b=1;
    echo $b;//输出1
    test($b);  //这里$b传递给函数的其实是$b的变量内容所处的内存地址,通过在函数里改变$a的值 就可以改变$b的值了
    echo "<br>";
    echo $b;//输出101

    要注意的是,在这里test(1);的话就会出错,原因自己去想

    函数的引用返回
    先看代码

    function &test()
    {
    static $b=0;//申明一个静态变量
    $b=$b+1;
    echo $b;
    return $b;
    }

    $a=test();//这条语句会输出 $b的值 为1
    $a=5;
    $a=test();//这条语句会输出 $b的值 为2

    $a=&test();//这条语句会输出 $b的值 为3
    $a=5;
    $a=test();//这条语句会输出 $b的值 为6

    下面解释下: 
    通过这种方式$a=test();得到的其实不是函数的引用返回,这跟普通的函数调用没有区别 至于原因: 这是PHP的规定
    PHP规定通过$a=&test(); 方式得到的才是函数的引用返回
    至于什么是引用返回呢(PHP手册上说:引用返回用在当想用函数找到引用应该被绑定在哪一个变量上面时。) 这句狗屁话 害我半天没看懂

    用上面的例子来解释就是
    $a=test()方式调用函数,只是将函数的值赋给$a而已, 而$a做任何改变 都不会影响到函数中的$b
    而通过$a=&test()方式调用函数呢, 他的作用是 将return $b中的 $b变量的内存地址与$a变量的内存地址 指向了同一个地方
    即产生了相当于这样的效果($a=&b;) 所以改变$a的值 也同时改变了$b的值 所以在执行了
    $a=&test();
    $a=5;
    以后,$b的值变为了5

    这里是为了让大家理解函数的引用返回才使用静态变量的,其实函数的引用返回多用在对象中

    对象的引用

    <?
    class a{
    var $abc="ABC";
    }
    $b=new a;
    $c=$b;
    echo $b->abc;//这里输出ABC
    echo $c->abc;//这里输出ABC
    $b->abc="DEF";
    echo $c->abc;//这里输出DEF
    ?>

    以上代码是在PHP5中的运行效果
    在PHP5中 对象的复制 是通过引用来实现的。上列中$b=new a; $c=$b; 其实等效于$b=new a; $c=&$b;
    PHP5中默认就是通过引用来调用对象, 但有时你可能想建立一个对象的副本,并希望原来的对象的改变不影响到副本 . 为了这样的目的,PHP定义了一个特殊的方法,称为__clone.

    引用的作用
    如果程序比较大,引用同一个对象的变量比较多,并且希望用完该对象后手工清除它,个人建议用 "&" 方式,然后用$var=null的方式清除. 其它时候还是用php5的默认方式吧. 另外, php5中对于大数组的传递,建议用 "&" 方式, 毕竟节省内存空间使用。


    取消引用
    当你 unset 一个引用,只是断开了变量名和变量内容之间的绑定。这并不意味着变量内容被销毁了。例如:

    <?php
    $a = 1;
    $b =& $a;
    unset ($a);
    ?>  

    不会 unset $b,只是 $a。


    global 引用
    当用 global $var 声明一个变量时实际上建立了一个到全局变量的引用。也就是说和这样做是相同的:

    <?php
    $var =& $GLOBALS["var"];
    ?>  

    这意味着,例如,unset $var 不会 unset 全局变量。

    $this
    在一个对象的方法中,$this 永远是调用它的对象的引用。


    //下面再来个小插曲
    php中对于地址的指向(类似指针)功能不是由用户自己来实现的,是由Zend核心实现的,php中引用采用的是“写时拷贝”的原理,就是除非发生写操作,指向同一个地址的变量或者对象是不会被拷贝的。

    通俗的讲
    1:如果有下面的代码

    $a="ABC";
    $b=$a;

    其实此时 $a与$b都是指向同一内存地址 而并不是$a与$b占用不同的内存

    2:如果在上面的代码基础上再加上如下代码

    $a="EFG";

    由于$a与$b所指向的内存的数据要重新写一次了,此时Zend核心会自动判断 自动为$b生产一个$a的数据拷贝,重新申请一块内存进行存储

    Tag:php
  • 2009-11-19

    转一个《 浅析豆瓣的 Google Analytics 应用》,备用

    大家好,我是owen,主要从事 Online marketing 方面的工作,平时主要专注于 SEM 和 Web analytics。这次很荣幸能够应 Denis 之邀,在我爱水煮鱼抛砖引玉,发表 Web analytics 方面的文章,希望以后能够在这里,与大家多多交流这方面的知识。今天首先给大家简单谈谈豆瓣网怎么应用 Google Analytics。

    豆瓣 Google Analytics 代码加载模式

    豆瓣从今年开始也加入 Google Analytics 的统计阵营。让我们通过它加载的 Google Analytics 源码,简单分析一下它都是怎么应用的。

    我们先从豆瓣的源码来看看它的Google Analytics统计代码

    豆瓣 Google Analytics 代码
    豆瓣 Google Analytics 代码

    我们知道一般默认的 Google Analytics代码如下:

    默认  Google Analytics 统计代码
    默认 Google Analytics 统计代码

    两相对比,我们就会发现豆瓣加载 ga.js 的方式与默认的方式有些不太一样,由于豆瓣并没有采用 https 加密访问,所以撇弃了默认的ga.js加载方式。

    默认的统计函数,pageTracker 也被豆瓣改成了 _ga ,这个只是名称定义上的区别,并没有什么实质的改变。豆瓣的主要应用是下面两个函数:

    使用 _ga._addOrganic 识别非主流搜索引擎

    再来看豆瓣比默认 Google Analytics 代码增加的部分,那就是多了数个 _ga._addOrganic ,这是 Google Analytics 添加自定义搜索引擎的代码。尽管 Google Analytics 对于主流的搜索引擎都能自动识别,但毕竟能识别的是国外的主流搜索引擎,在国内,像搜狐的 Sogou,QQ 的 soso,网易的有道等搜索引擎,都不能被 Google Analytics 正确识别,而被当作推荐来源。这时候我们就可以利用_addOrganic 参数来识别这些非主流搜索引擎,如豆瓣的做法。

    使用 _addIgnoredOrganic 忽略关键字

    除了添加自定义搜索引擎,豆瓣在最后还添加了如下这些代码:

    _ga._addIgnoredOrganic("豆瓣");
    _ga._addIgnoredOrganic("douban");
    _ga._addIgnoredOrganic("豆瓣网");
    _ga._addIgnoredOrganic("www.douban.com");

    这些代码用来把引号中的关键词从搜索引擎的关键词报告中排除,而当成直接点击量来源。

    为什么要这么做?因为一个知名的大网站,来自这些品牌词的搜索流量都非常大,常常是排在前几位的搜索关键词来源,而这通常是因为搜索引擎养成现在的 人都懒得记网址,直接搜索品牌名来记住域名。这些品牌词对于网站的关键词来源分析并没有很直接的帮助,所以在来自品牌词的流量很大的情况下,可以直接把这 些关键词识别成直接点击量来源。

    关于自定义 Google Analytics 搜索引擎排除特定关键词为直接点击量来源的语法,可以参考 Google Code 上关于这方面的详细介绍。

    通过 _setVar 识别用户

    当我们登录豆瓣后,再来分析豆瓣的源码,会发现多了一个ga._setVar(”xxxx”)的 Google Analytics 参数。

    豆瓣使用 Google Analytics 的._setVar参数来跟踪登录用户行为
    豆瓣使用 Google Analytics 的._setVar参数来跟踪登录用户行为

    _setVar() 函数是 Google Analytics 的用户定义函数,主要用于对特定来源的用户行为进行分类,例如可以对登录浏览的用户设置一个数值,然后在 Google Analytics 后台的访问者/用户定义 中查看其浏览属性。

    Google Analytics 访问者/用户定义报告
    Google Analytics 访问者/用户定义报告

    分析豆瓣的源码可以知道,豆瓣对每一个登录后的用户,都赋以一个专门的 id 值,这样可以在用户定义报告里,看到整体的登录用户访问行为,乃至每个登录用户的浏览行为。通过这样设定后,豆瓣便可以轻易获取高忠诚度访问用户的访问行为。关于_setVar()的更多说明,请参阅 Google Analytics的技术文档

    如何根据访问者在我的网站上访问的页面或在表单上做出的响应对其进行分类?在 Google Analytics 官方的帮助文件,也给出了另外一个应用案例

    值得注意的是,原来在设置 _setVar() 函数的时候,整个网站的跳出率会出现重大的偏差,不过在最近的google analytics官方博客,指出该bug已经修正,客户在进行这方面设置的时候,还是要注意对比前后数据是否有重大偏差。

    通过 _trackPageview 区分不同类型的评论

    豆瓣上的书评,影评和乐评可以说是豆瓣网站的核心价值所在。一般评论的URL格式如下:

    豆瓣上单条评论的URL
    豆瓣上单条评论的URL

    当我们查看该页面的网页源代码时,会发现有趣的现象:

    豆瓣单条评论页的 Google Analytics 代码
    豆瓣单条评论页的 Google Analytics 代码

    我们知道,一般 Google Analytics 的_trackPageview() 括弧中的参数是留空的, Google Analytics 会自动捕获网址的 URL 参数,如果在 _trackPageview()括弧中输入特定的数值,那么在 Google Analytics 的报表中,URL 将是我们指定的参数,而不再是我们在地址栏看到的 URL。

    如上面的例子,我们在 Google Analytics 中看到的URL将是/book/review/1946018/,而不再是我们在浏览器地址栏看到的/review/1946018/

    当所在频道是电影或者音乐时,_trackPageview() 中的参数将根据所在频道的属性,变为/movie/xxxxx 或者 /music/xxxxx的数值。

    豆瓣通过对的参数进行重新指定,主要有以下的好处:

    保证了用户和搜索引擎看到的 URL 比较简短,达到 URL 对用户友好和对搜索引擎友好的目的;而在 Google Analytics 报告中,通过 内容/内容细目/ 报告,又能了解到各个频道总的浏览情况。

    在GA的内容细目报告中,将会多出 /book/ /music/ /movie/ 这样的文件夹来,总而获得各个频道的合计浏览数据。

    而如果只是使用默认 _trackPageview(),你将只能得到所有评论页面的浏览数据,而无法得到细分的各个频道的浏览数据。

    关于_trackPageview()的具体的使用方法可参照 Google Code 的说明

    注意事项:使用 _trackPageview() 参数重新指定 URL 之后,网站覆盖图的数据将受到影响。可参阅 Google Analytics 的官方帮助文件

    除了豆瓣使用 _trackPageview() 来对URL进行重写,大众点评网也采用了类似的做法(应该是比豆瓣更早采用。。。因为是我在点评网任职时候实验的做法;那时候豆瓣还没有使用 Google Analytis 统计代码,呵呵),有兴趣的同学可以自己去研究点评的 Google Analytis 代码。

    Tag:
  • 2009-11-17

    一些PHP的Tips,面试会遇到 - [php]

     

    HTTP协议中几个状态码的含义:503 500 401 200 301 302
        2xx: (成功)
        3xx (重定向)
        4xx: Client Error 使用者端(浏览器)错误讯息
        5xx: Server Error  服务器端错误讯息
        400(错误请求)     服务器不理解请求的语法。
        401(未授权)     请求要求身份验证。对于登录后请求的网页,服务器可能返回此响应。
        500(服务器内部错误)     服务器遇到错误,无法完成请求。
        503(服务不可用)     服务器目前无法使用(由于超载或停机维护)。通常,这只是暂时状态。

    Include require include_once require_once 的区别.
        require() :如果文件不存在,会报出一个fatal error.脚本停止执行
        include() : 如果文件不存在,会给出一个 warning,但脚本会继续执行
        _once: 会检测是否包含过了,包含过了就不包含了

    关于HereDOC:
        <?php
        $a = "---------";
        echo <<<HAHA
        $a
        \$a
        HAHA
        ?>
        输出:   -----------
                    $a

    关于php的魔法引用:
        如果php.ini不可改,可以使用.htaccess文件禁用,加入下面的代码 php_flag magic_quotes_gpc Off
        相关函数:stripslashes — 去掉反斜杠,得到原始数据。       addslashes — 使用反斜线引用字符串

        最好设置为OFF,然后自己过滤,在PHP6中已经关闭了,或者用下面的函数:
        if (get_magic_quotes_gpc())
        {
            function stripslashes_deep($value)
            {
                $value = is_array($value)?array_map('stripslashes_deep',$value):stripslashes($value);
                return $value;
            }
            $_GET     = array_map('stripslashes_deep', $_GET);
            $_POST    = array_map('stripslashes_deep', $_POST);
            $_COOKIE  = array_map('stripslashes_deep', $_COOKIE);
            $_REQUEST = array_map('stripslashes_deep', $_REQUEST);
        }

    一些编译php时的configure 参数
    1.作为APACHE模块编译
    –with-apxs2
    2.作为fastcgi编译
    –enable-fastcgi
    –enable-force-cgi-redirect
    3.动态加载PHP的extension
    加载模块的后面加上shared关键词
    例如–with-gd=shared
    4.enable的扩展选项一样可以使用shared关键词作为外部扩展模块载入
    5.with-EXTENSIONS-dir和单纯的with-EXTENSIONS的作用相同
    同样是指定加载特定模块
    只是可以指定目录
    ./configure --prefix=/usr/local/php --with-config-file-path=/etc \
    --with-apxs2 --enable-fastcgi --enable-force-cgi-redirect \
    --with-gd=shared \
    --with-jpeg-dir \
    --with-png-dir \
    --with-zlib-dir \
    --enable-gd-native-ttf \
    --with-freetype-dir=shared \
    --with-zlib=shared \
    --with-mysql=shared \
    --with-mcrypt=shared \
    --with-pear=shared \
    --with-curl=shared \
    --with-curlwrappers=shared \
    --with-xmlrpc=shared \
    --without-sqlite --disable-debug --disable-rpath \
    --enable-mbstring=shared \
    --enable-exif=shared \
    --enable-zip=shared \
    --enable-ftp=shared

    Safe_mode 打开后哪些地方受限.
    启动safe_mode,会对许多PHP函数进行限制,特别是和系统相关的文件打开、命令执行等函数。

    解决多进程/线程同时读写一个文件的问题

    对于日IP不高或者说并发数不是很大的应用,一般不用考虑这些!!用一般的文件操作方法完全没有问题。但如果并发高,在我们对文件进行读写操作时,很有可能多个进程对进一文件进行操作,如果这时不对文件的访问进行相应的独占,就容易造成数据丢失。

    对于这样的问题,一般的解决方案时当一进程对文件进行操作时,首先对其它进行加锁
    所以一般的方案是:
    $fp = fopen("/tmp/lock.txt", "w+");
    if (flock($fp, LOCK_EX)) {
        fwrite($fp, "Write something here\n");
        flock($fp, LOCK_UN);
    } else {
        echo "Couldn't lock the file !";
    }
    fclose($fp);

    但在PHP中,flock似乎工作的不是那么好!在多并发情况下,似乎是经常独占资源,不即时释放,或者是根本不释放,造成死锁,从而使服务器的cpu占用很高,甚至有时候会让服务器彻底死掉。好像在很多linux/unix系统中,都会有这样的情况发生。

    如果不考虑使用flock()函数,也同样会有很好的解决方案来解决我们的问题。
    方案一:对文件进行加锁时,设置一个超时时间.

    if($fp = fopen($fileName, 'a')) {
        $startTime = microtime();
        do {
                $canWrite = flock($fp, LOCK_EX);
            if(!$canWrite) usleep(round(rand(0, 100)*1000));
        } while ((!$canWrite) && ((microtime()-$startTime) &lt; 1000));
        if ($canWrite) {
          fwrite($fp, $dataToSave);
        }
        fclose($fp);
    }
    超时设置为1ms,如果这里时间内没有获得锁,就反复获得,直接获得到对文件操作权为止,当然。如果超时限制已到,就必需马上退出,让出锁让其它进程来进行操作。
    方案二:不使用flock函数,借用临时文件来解决读写冲突的问题。
    大致原理如下:
    1。将需要更新的文件考虑一份到我们的临时文件目录,将文件最后修改时间保存到一个变量,并为这个临时文件取一个随机的,不容易重复的文件名。
    2。当对这个临时文件进行更新后,再检测原文件的最后更新时间和先前所保存的时间是否一致。
    3。如果最后一次修改时间一致,就将所修改的临时文件重命名到原文件,为了确保文件状态同步更新,所以需要清除一下文件状态。
    4。但是,如果最后一次修改时间和先前所保存的一致,这说明在这期间,原文件已经被修改过,这时,需要把临时文件删除,然后返回false,说明文件这时有其它进程在进行操作。

    方案四:将所有要操作的进程放入一个队列中。然后专门放一个服务完成文件操作。
    队列中的每一个排除的进程相当于第一个具体的操作,所以第一次我们的服务只需要从队列中取得相当于具体操作事项就可以了,如果这里还有大量的文件操作进程,没关系,排到我们的队列后面即可,只要愿意排,队列的多长都没关系。
    参考:http://hqlong.com/2009/01/530.html

    使用mod_rewrite,在服务器上没有/archivers/567.html这个物理文件时,重定向到index.php?id=567

    先php.ini配置中打开mod_rewrite。然后在.htaccess文件中写入:ErrorDocument 404 index.php?id=567

    对于大流量的网站,您采用什么样的方法来解决各页面访问量统计问题

    网站性能优化 提高网站访问速度的14条实践规则

    具体参考:提高网站性能的14条法则:http://www.629d.com/a/200907/62.html

    主要:

    第一条、尽可能的减少 HTTP 的请求数 (Make Fewer HTTP Requests )
    第二条、使用CDN(内容分发网络): Use a Content Delivery Network
    第三条、 添加Expire/Cache-Control 头:Add an Expires Header
    第五条、将css放在页面最上面 ( Put Stylesheets at the Top)
    第六条、将script放在页面最下面 (Put Scripts at the Bottom )


    Tag:php tips
  • 2009-11-17

    应该具有什么样的技能,才算得上PHP程序员?

    应该具有什么样的技能,才算得上PHP程序员?你的技术又是在什么水平级别上? CU上的BS同学写了以下文章。欢迎各位对号入座。

    1、PHP编程能力

    说不清,留空

    2、MySQL能力
    在开发上的应用基于几个能力体现:
    1、了解:知道用PHP连接数据库;懂得写一些简单的SQL;建一些简单的索引;懂得用工具简单操作一下数据库(增删改库表结构数据等等)。
    2、熟悉:懂得在开发应用上设计数据库,建立一些有效的索引,用explain分析SQL性能,压力测试等等。
    3、很熟悉:深入了解数据库索引、存储引擎原理以及运行机制,能有效地构建高性能可扩展的数据库结构/架构,有效地优化数据库性能配置并加以调试,分析数据库运行状态。
    4、精通:简单地说具备以上所有能力的同时,有多年高负载分布式环境下的优化管理经验。


    据我观察以及交往经验,70%的PHPer处在了解阶段,25%处于熟悉阶段,>4%很熟悉,精通的人基本就不是phper了。

    70%这个群体最容易忽视MySQL,以为MySQL只是简单的存储媒介,没有优化意识,认为加个内存、CPU就能解决问题。
    典型事件:join、order by、group by等语句性能一塌糊涂,数据库根本没有设计(仅限于拆成一个主表,N个附表等),搞不清字段类型及作用,碰到大表的复杂查询就没辙。

    20%这个群体的人只是MySQL运行机制理解不透彻,对影响MySQL性能的关健因素把握不明确,不熟练。
    典型事件:熟读手册,但说不清索引原理,不知道二叉树、HASH等算法对于数据库的作用

    >4%的群体已经基本可以胜任DBA的职能。

    3、OOP能力
    1、了解:了解变量的作用域、类型,及其意义,了解继承机制等,懂得复用、封装概念。
    2、熟悉:熟练应用接口、抽象等技术混合开发程序,并理解其中含义,一般研究过JAVA。
    3、很熟悉:有过OOP架构设计经验,熟悉设计模式、UML,熟悉PHP对象运行机制,内容管理等。
    4、精通:应该是架构师级别了,不限于PHP。

    经常我们会碰到一些自称熟悉OOP却连public、private、protected、static都解释不清的人,是肯定没有经历过正规的OOP项目。

    4、大型网站经验
    1、了解:熟悉PHP开发下的缓存应用(memcache、APC等);接触过LVS、SQUID应用;
    有一定的session处理方案;熟悉负载均衡;熟悉PHP数据连接池应用;了解PHP编程性能优化。
    2、熟悉:掌握分布式缓存及缓存性能优化、熟悉存储系统、文件系统、数据库,开发可扩展平台。能结合负载均衡合理布置流量,对PHP运行性能进行监控与分析。
    3、非常熟悉:具备系统分析师能力,已经超出phper环节...
    4、精通:太深奥..

    5、DOM开发能力
    留空

    6、*nux应用能力
    ...
    ------------------------------------------------------------------------------------------------

    路漫漫其修远兮,吾将上下而求索

    Tag:
  • 2009-11-11

    我的第一个python脚本 - [python]

    呵呵,最近在学习python,只明白了大概,很多还不会,不熟悉。现在放一个python程序,目标是:遍历文件夹里的torrent文件,分析hash info 加密后是否跟原文件的文件名相同,不同的话,记录log文件。我写起来有点复杂,感觉还不是按照python的思维来写程序,要学的还很多。

    #! /usr/bin/python

    from sys import *
    from bencode import *
    import hashlib
    import os
    import os.path

    #-----test-----
    #if len(argv) != 2:
    #    print "ERROR: use ./33.py filename"
    #    exit(2)
    #file_name = argv[1]
    #-----test-----

    def check_torrent_hash(file_name):
        filename ='torrent/'+file_name
        metainfo_file = open(filename, 'rb')
        if metainfo_file:
            metainfo = bdecode(metainfo_file.read())
        else:
            print "ERROR: Not a valid torrent file"
            exit(1)
        metainfo_file.close()
        info = metainfo['info']
        hahaha =  bencode(info)
        mySha1 = hashlib.sha1()   
        mySha1.update(hahaha)
        mySha1_Digest = mySha1.hexdigest()
        up_str = mySha1_Digest.upper();
        OK = file_name.split('.')   
        #print up_str
        #print OK[0]
        if not up_str==OK[0]:
            error_file = open('/home/changyou/wget/error.log', 'a+')
            error_file.writelines(up_str+'\n')
            error_file.close()
            return 'NO~~please check /home/changyou/wget/error.log'
        else:
            return 'OK!!!'

    rootdir = "/home/changyou/wget/torrent/"
    for parent, dirnames, filenames in os.walk(rootdir):
        for filename in filenames:
            print check_torrent_hash(filename)


     

  • 2009-11-10

    python取BT种子的hashinfo - [python]

    折腾了1天,BT果然是变态,名副其实。

    BT是python编写,他的种子文件时以Bencoding编码格式编码,具体如下
    无论是web服务器提供的那个.torrent文件,还是peers和trackers进行的信息交互,都是基于Bencoding格式的。
    1 字符串:首先是字符串长度,然后是一个:号,接着是串内容,比如5:hello,就是指hello这个字符串。
    2 整数:以“i”开头(int的意思),然后是十进制数字,最后是一个“e”结尾,如i3e表示3,i-3e表示-3,i0e表示0,i-0e是非法的。
    3 列表:以“l”开头(list的意思),以“e”结尾。比如 l5:hello5:worldi1234ee 代表 ["hello","world",1234]
    4 字典:以“d”开头(dictionary),以“e”结尾。比如 d3:cow3:moo4:spam4:eggse,则代表{"cow":"moo", "spam","eggs"}

    这里,我们要取的info是种子文件里‘字典’info后面的所有(包括d,到最后的包括e),很长一串。

    最开始写了一个PHP脚本,只是分析的种子文件,只是把种子文件里的数据用数组的形式显,然后用函数sha1(),结果得到的hashinfo不正确。崩溃ing

    后来google了下,发现用python比较靠谱,因为有现成的模块,代码如下:

    #! /usr/bin/python
    ffrom sys import *
    from bencode import *
    import hashlib

    mySha1 = hashlib.sha1()  //新建对象
    if len(argv) != 2:
        print "ERROR: use ./hash_info.py filename"

        exit(2)
    filename = argv[1]
    metainfo_file = open(filename, 'rb')
    try:
        metainfo = bdecode(metainfo_file.read())
    except ValueError:
        print "ERROR: Not a valid torrent file"
        exit(1)
    metainfo_file.close()
    info = metainfo['info'] //取列表的info
    hahaha =  bencode(info) //取torrent的info

    mySha1.update(hahaha)
    mySha1_Digest = mySha1.hexdigest()
    print mySha1_Digest  //得到info sha加密后的数据!!

    ---------------------------------------------------------------------

    注意:在linux下自带的python里没有hashlib模块,和bencod模块

    需要下载安装,hashlib     http://code.krypto.org/python/hashlib/

    bencod需要下载BitTorrent源码,或者下载单独文件:http://www.pinking.net.cn/scrip/bencode.py,跟脚本程序放在同一目录下即可

  • 2009-10-14

    7个简易网页效果mootools插件 - [JQuery]

    最近研究,前台展示的东西,发觉会的东西实在是少,不会div切图,JS也不咋地,看来要学习的还很多啊。转帖,留下以备后用!

    脚本的最大优点就是仅仅一小段巧妙就可以极大地提升网站的用户体验,得意于Mootools开发社区非常擅长于开发一些专业的高质量插件,我今天可 以收集到一些值得在网站设计中使用的插件,他们可以帮助你提高网站用户体验到一个新的层次,当前前提是你喜欢mootools。

    引文原文:http://davidwalsh.name/7-mootools-plugins

    AutoGrow

    我很确信文本域和文本框都应该提供一个可以自动放大的效果,AutoGrow 可以让文本域的大小自动的渐变,这样你即便输入很多容内也可以在文本域内完整的看到所有内容。
    Download && DEMO 

    Fancy Form

    FancyForm

    FancyForm 是checkbox增强插件,用来替换表单中奇丑的checkbox和radio,FancyForm 的样式完全由css控制。

    Website & Download Documentation Example Usage

     

    Milkbox

    Milkbox

    图片丰富的网站都少补了一个好的灯箱效果(更多的灯箱效果可以猛点这里:http://jsssc.cn/30-useful-ajax-lightbox-and-modal-dialog-solutions/)插件,Milkbox包含了实现所有灯箱效果的脚本,它可以轻松实现各种经典的渐变效果到页面元素上,经常用在flash视频,图片集,xml画廊。

    Website, Download, Documentation, & Example Usage

     

    Quickboxes

    不要让用户一个亿个去点击很多的复选框,Quickboxes允许通过点击并拖动来同时选中多个复选框,只需点击其中一个然后拖动鼠标,有鼠标经过 的复选框都可以被选中(也可以设置成切换选中状态),有时候你的用户可能需要选中复选框中的一部分而已, Quickboxes可以帮你忙。

    Website & Download Documentation Example Usage

     

    SmoothScroll

    SmoothScroll可以让页面缓缓地移动到指定的锚点,从而可以代替默认的跳动效果。

    Website & Download Documentation Example Usage

     

    MooTools Tooltip

    Tips

    Tips是用来代替默认的提示title的效果,它帮你创建富有质感的提示框。

    Website & Download Documentation Example Usage

     

    Zebra Tables

    ZebraTables

    ZebraTables 帮你实现表格的隔行换色、单击变色、鼠标滑过变色效果。

    Website & Download Documentation Example Usage

    Tag:JS
  • 2009-09-25

    mysql 关于索引 - [mysql]

    MySQL索引 在数据库表中,对字段建立索引可以大大提高查询速度。假如我们创建了一个 mytable表:

    CREATE TABLE mytable(

    ID INT NOT NULL,

    username VARCHAR(16) NOT NULL

    );

    我们随机向里面插入了10000条记录,其中有一条:5555, admin。

    在查找username="admin"的记录 SELECT * FROM mytable WHERE username='admin';时,如果在username上已经建立了索引,MySQL无须任何扫描,即准确可找到该记录。相反,MySQL会扫描 所有记录,即要查询10000条记录。

    索引分单列索引和组合索引。单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。组合索引,即一个索包含多个列。

    索引的类型包括:

    (1)普通索引
    这是最基本的索引,它没有任何限制。它有以下几种创建方式:

    ●     创建索引

    CREATE INDEX indexName ON mytable(username(length));

    如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定 length,下同。

    ●     修改表结构

    ALTER mytable ADD INDEX [indexName] ON (username(length))

    ●     创建表的时候直接指定

    CREATE TABLE mytable(

    ID INT NOT NULL,

    username VARCHAR(16) NOT NULL,

    INDEX [indexName] (username(length))

    );

    删除索引的语法:

    DROP INDEX [indexName] ON mytable;

    (2)唯一索引
    它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式:

    ●     创建索引

    CREATE UNIQUE INDEX indexName ON mytable(username(length))

    ●     修改表结构

    ALTER mytable ADD UNIQUE [indexName] ON (username(length))

    ●     创建表的时候直接指定

    CREATE TABLE mytable(

    ID INT NOT NULL,

    username VARCHAR(16) NOT NULL,

    UNIQUE [indexName] (username(length))

    );

    (3)主键索引
    它是一种特殊的唯一索引,不允许有空值。一般是在建表的时候同时创建主键索引:

    CREATE TABLE mytable(

    ID INT NOT NULL,

    username VARCHAR(16) NOT NULL,

    PRIMARY KEY(ID)

    );

    当然也可以用 ALTER 命令。记住:一个表只能有一个主键。

    (4)组合索引
    为了形象地对比单列索引和组合索引,为表添加多个字段:

    CREATE TABLE mytable(

    ID INT NOT NULL,

    username VARCHAR(16) NOT NULL,

    city VARCHAR(50) NOT NULL,

    age INT NOT NULL

    );

    为了进一步榨取MySQL的效率,就要考虑建立组合索引。就是将 name, city, age建到一个索引里:

    ALTER TABLE mytable ADD INDEX name_city_age (name(10),city,age);

    建表时,usernname长度为 16,这里用 10。这是因为一般情况下名字的长度不会超过10,这样会加速索引查询速度,还会减少索引文件的大小,提高INSERT的更新速度。

    如果分别在 usernname,city,age上建立单列索引,让该表有3个单列索引,查询时和上述的组合索引效率也会大不一样,远远低于我们的组合索引。虽然此时有了三个索引,但MySQL只能用到其中的那个它认为似乎是最有效率的单列索引。

    建立这样的组合索引,其实是相当于分别建立了下面三组组合索引:

    usernname,city,age

    usernname,city

    usernname

    为什么没有 city,age这样的组合索引呢?这是因为MySQL组合索引“最左前缀”的结果。简单的理解就是只从最左面的开始组合。并不是只要包含这三列的查询都会用到该组合索引,下面的几个SQL就会用到这个组合索引:

    SELECT * FROM mytable WHREE username="admin" AND city="郑州"

    SELECT * FROM mytable WHREE username="admin"

    而下面几个则不会用到:

    SELECT * FROM mytable WHREE age=20 AND city="郑州"

    SELECT * FROM mytable WHREE city="郑州"

    (5)建立索引的时机
    到这里我们已经学会了建立索引,那么我们需要在什么情况下建立索引呢?一般来说,在WHERE和JOIN中出现的列需要建立索引,但也不完全如此,因为 MySQL只对<,<=,=,>,>=,BETWEEN,IN,以及某些时候的LIKE才会使用索引。例如:

    SELECT t.Name

    FROM mytable t LEFT JOIN mytable m

    ON t.Name=m.username WHERE m.age=20 AND m.city='郑州'

    此时就需要对city和age建立索引,由于mytable表的userame也出现在了JOIN子句中,也有对它建立索引的必要。

    刚才提到只有某些时候的LIKE才需建立索引。因为在以通配符%和_开头作查询时,MySQL不会使用索引。例如下句会使用索引:

    SELECT * FROM mytable WHERE username like'admin%'

    而下句就不会使用:

    SELECT * FROM mytable WHEREt Name like'%admin'

    因此,在使用LIKE时应注意以上的区别。

    (6)索引的不足之处
    上面都在说使用索引的好处,但过多的使用索引将会造成滥用。因此索引也会有它的缺点:

    ●     虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。

    ●     建立索引会占用磁盘空间的索引文件。一般情况这个问题不太严重,但如果你在一个大表上创建了多种组合索引,索引文件的会膨胀很快。

    索引只是提高效率的一个因素,如果你的MySQL有大数据量的表,就需要花时间研究建立最优秀的索引,或优化查询语句。

    (7)使用索引的注意事项
    使用索引时,有以下一些技巧和注意事项:

    ●     索引不会包含有NULL值的列

    只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为NULL。

    ●     使用短索引

    对串列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个CHAR(255)的列,如果在前10个或20个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。

    ●     索引列排序

    MySQL查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。

    ●     like语句操作

    一般情况下不鼓励使用like操作,如果非使用不可,如何使用也是一个问题。like “%aaa%” 不会使用索引而like “aaa%”可以使用索引。

    ●     不要在列上进行运算

    select * from users where YEAR(adddate)<2007;将在每个行上进行运算,这将导致索引失效而进行全表扫描,因此我们可以改成select * from users where adddate<‘2007-01-01’;

    ●     不使用NOT IN和<>操作

    NOT IN和<>操作都不会使用索引将进行全表扫描。NOT IN可以使用NOT EXISTS代替,id<>3则可以使用id>3 or id<3来代替。

    Tag:Mysql
  • 2009-09-22

    用nginx的反向代理做负载均衡 - [service]

    1. ngnix之所以比apache高效,得益于Nginx使用了最新的epoll(Linux 2.6内核)和kqueue(freebsd)网络I/O模型,而Apache则使用的是传统的select模型。目前Linux下能够承受高并发访问的 Squid、Memcached都采用的是epoll网络I/O模型。也就是说,在高并发服务器中,轮询(round-robin)I/O是最耗时间的操作。

    2. 反向代理工作原理
    反向代理服务器位于本地WEB服务器和Internet之间.
    当用户浏览器发出一个HTTP请求时,通过域名解析将请求定向到反向代理服务器(如果要实现多个WEB服务器的反向代理,需要将多个WEB服务 器的域名都指向反向代理服务器)。由反向代理服务器处理器请求。反向代理一般只缓存可缓冲的数据(比如html网页和图片等),而一些CGI脚本程序或者 ASP之类的程序不缓存。它根据从WEB服务器返回的HTTP头标记来缓冲静态页面。有四个最重要HTTP头标记:

    Last-Modified: 告诉反向代理页面什么时间被修改
    Expires: 告诉反向代理页面什么时间应该从缓冲区中删除
    Cache-Control: 告诉反向代理页面是否应该被缓冲
    Pragma: 告诉反向代理页面是否应该被缓冲.
    例如:在默认情况下,ASP页面返回” Cache-control: private.” ,所以ASP页面时不会在反向代理服务器缓存的。

    ----------------------------------------------------------------------------------

    3. ngnix最常见的用法之一就是作为反向代理使用,安装和配置相当简便,对于负载均衡它使用的是最简单的轮询算法(round-robin),不过效果还是很不错的。

    要用nginx做负载均衡的话,首先要在配置文件里面定义一组用来负载均衡的后端服务器(backend servers),例如:
    upstream backend {
      server 192.168.1.11;
      server 192.168.1.12;
      server 192.168.1.13;
    }

    那个server指令的语法是 server name [parameters],这里的name是服务器名,可以是域名、ip或者unix socket,也可以指定端口,例如:
    server 192.168.1.11:8080;

    server指令可用的参数有:

    weight —— 设置服务器的权重,默认值是1,权重值越大那么该服务器被访问到的几率就越大,例如 server 192.168.1.11 weight=5;

    max_fails和fail_timeout —— 这俩是关联的,如果某台服务器在fail_timeout时间内出现了max_fails次连接失败,那么nginx就会认为那个服务器已经挂掉,从而在 fail_timeout时间内不再去查询它,fail_timeout的默认值是10s,max_fails的默认值是1(这意味着一发生错误就认为服 务器挂掉),如果把max_fails设为0则表示把这个检查取消。
    举个例子:server 192.168.1.11 max_fails=3 fail_timeout=30s; 这表示,如果服务器192.168.1.11在30秒内出现了3次错误,那么就认为这个服务器工作不正常,从而在接下来的30秒内nginx不再去访问这个服务器。

    down —— 表示该服务器已经停用,例如server 192.168.1.11 down;

    backup —— 表示该服务器是备用服务器,只有其它后端服务器都挂了或者很忙才会访问到。

    关于upstream的更多信息请参考 http://wiki.nginx.org/NginxHttpUpstreamModule

    定义好了一组后端服务器,就该来设置nginx的反向代理配置了,例如:
    server {
      listen 80;
      server_name www.domain.com;
      location / {
        proxy_pass http://backend;
      }
    }

    关于nginx的proxy有很多配置参数的,具体可以参考 http://wiki.nginx.org/NginxHttpProxyModule
    这里有个配置可能比较有用:
    proxy_set_header Host $host;
    这表示传递给后端服务器的头部信息里面的Host信息保持跟客户端传过来的一致,如果不设置那么默认传给后端服务器的值是$proxy_host,所以不 设置可能会有问题,例如:后端服务器会处理两个域名的请求,例如www.a.com和www.b.com,这时如果nginx不把客户端的请求信息中的 host信息传给后端服务器,那么后端服务器完全不知道到底这个客户是想访问域名a还是域名b,从而导致传输数据可能不正确。
    如果你想把客户端的ip也传给后端服务器的话,可以用这个设置:
    proxy_set_header X-Real-IP $remote_addr;

    4. 负载均衡
    参考:http://blog.s135.com/nginx_php_v5/
  • 2009-09-14

    http_load 一个httpd 压力测试工具 - [service]

    到http://www.acme.com/software/http_load/ 下载http_load ,安装也很简单直接make;make instlall 就行。

    http_load的标准的两个例子是:

    1. http_load -parallel 5 -fetches 1000 urls.txt  
    2. http_load -rate 2 -seconds 300 urls.txt  

     

    例子只是个参考,参数其实可以自由组合,参数之间的选择并没有什么限制。比如你写成http_load -parallel 5 -seconds 300 urls.txt也是可以的。我们把参数给大家简单说明一下。-parallel 简写-p 含义是并发的用户进程数。

    -fetches 简写-f 含义是总计的访问次数

    -rate    简写-p 含义是每秒的访问频率

    -seconds简写-s 含义是总计的访问时间


    urls.txt 是一个url 列表,每个url 单独的一行。当然也可以直接跟一个url 而不是url 列表文件。
    实例:
    1. http_load -rate 5 -seconds 10 urls  
    2. 49 fetches, 2 max parallel, 289884 bytes, in 10.0148 seconds  
    3. 5916 mean bytes/connection  
    4. 4.89274 fetches/sec, 28945.5 bytes/sec  
    5. msecs/connect: 28.8932 mean, 44.243 max, 24.488 min  
    6. msecs/first-response: 63.5362 mean, 81.624 max, 57.803 min  
    7. HTTP response codes:  
    8.   code 200 -- 49  
     
    分析:
    1.49 fetches, 2 max parallel, 289884 bytes, in 10.0148 seconds
    说明在上面的测试中运行了49个请求,最大的并发进程数是2,总计传输的数据是289884bytes,运行的时间是10.0148秒

    2.5916 mean bytes/connection
    说明每一连接平均传输的数据量289884/49=5916

    3.4.89274 fetches/sec, 28945.5 bytes/sec
    说明每秒的响应请求为4.89274,每秒传递的数据为28945.5 bytes/sec

    4.msecs/connect: 28.8932 mean, 44.243 max, 24.488 min
    说明每连接的平均响应时间是28.8932 msecs,最大的响应时间44.243 msecs,最小的响应时间24.488 msecs

    5.msecs/first-response: 63.5362 mean, 81.624 max, 57.803 min

     6、HTTP response codes: code 200 -- 49
    说明打开响应页面的类型,如果403的类型过多,那可能要注意是否系统遇到了瓶颈。
    特殊说明:这里,我们一般会关注到的指标是fetches/sec、msecs/connect
    他们分别对应的常用性能指标参数Qpt-每秒响应用户数和response time,每连接响应用户时间。测试的结果主要也是看这两个值。当然仅有这两个指标并不能完成对性能的分析,我们还需要对服务器的cpu、men进行分析,才能得出结论
  • 2009-08-25

    mysqldumpslow分析mysql运行 - [mysql]

    mysql自带的这个玩意挺好使的,可以对慢查询里的sql进行排序、计算等操作。

    首先得配置my.cnf:
    log_slow_queries = /path/slow.log # 定义log位置,注意要有写入的权限

    具体的使法如下:
    mysqldumpslow -s c -t 40 /path/slow.log

    出来的结果是访问次数最多的40个sql,几个参数大概意思如下:

    -t 显示多少条
    -s 排序,默认是at。c是次数,t是时间,l是lock时间,r是返回结果。如果是ac,at,al,ar则是倒序
    -g 可以用正则匹配部分语句

    可以参考mysqldumpslow --help,通过这个工具可以看到哪些锁表,或者其他性能问题,还能看到某些SQL_NO_CACHE提示呢,去想办法优化把!

    Tag:Mysql
  • 2009-08-25

    Nginx中文参考资料!! - [service]

    http://code.google.com/p/nginxsrp/wiki/NginxCodeReview

    概述:
    Nginx
     ("engine x") 是一个高性能的 HTTP 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器
    Nginx 是由 Igor Sysoev 为俄罗斯访问量第二的Rambler.ru 站点开发的,它已经在该站点运行超过四年多了。
    Igor 将源代码以类BSD许可证的形式发布。自Nginx 发布四年来,Nginx 已经因为它的稳定性、丰富的功能集
    、示例配置文件和低系统资源的消耗而闻名了。目前国内各大门户网站已经部署了Nginx
    如新浪、网易、腾讯等;国内几个重要的视频分享网站也部署了Nginx,如六房间、酷6等。
    新近发现Nginx 技术在国内日趋火热,越来越多的网站开始部署Nginx
    Tag:nginx
  • 2009-08-21

    中文全文搜索解决方案sphinx+mysql+mmseg,安装,配置,API调用 - [service]

    最近在研究中文搜索引擎,找了许多解决方案,有JAVA下的的Lucene,还有强大的C++下的fietex,哪些比较复杂,对现在的项目来讲,不是很实用,所以把目光瞄向了轻便的sphinx,今天安装还算顺利,以下备忘。
    首先,Sphinx默认不支持中文索引及检索,以前用补丁搞定,现在,写补丁那个项目组的人又弄了个CSFT,全称是:CoreSeek Fulltext Search Server,CoreSeek 全文检索服务器。于是呢,就把sphinx集成过来,挺好用的。

    1. 去Coreseek官网下载源码,需要mmseg和Coreseek Fulltext Server最好用源码安装,那个RPM文件包反正我没搞定,呵呵。
    2. 装mmseg。
          # tar zxf mmseg3_0b3.tar.gz
          # cd mmseg3_0b4;
          # ./configure –prefix=/Data/apps/mmseg
    (这个目录可以改)
          # make && make install
         运行mmseg,如果成功会有显示
         
    3. 装CSFT   
      # tar zxf csft3_0b4.tar.gz
          # cd csft3_0b3
          # ./configure -prefix=/Data/apps/sphinx  (这个需要mysql和mmseg,别把目录写错了)
          -with-mysql=/Data/apps/mysql        
          -with-mmseg=/Data/apps/mmseg
          -with-mmseg-includes=/Data/apps/mmseg/include/mmseg
          -with-mmseg-libs=/Data/apps/mmseg/lib/
          -with-mysql-includes=/Data/apps/mysql/include/mysql/
          -with-mysql-libs=/Data/apps/mysql/lib/mysql/
          # make && make install


    4. sphinx.conf
        安装完成后,会生成/Data/apps/sphinx/etc/sphinx.conf.dist  要更改为.conf
        #cp /Data/apps/sphinx/etc/sphinx.conf.dist /Data/apps/sphinx/etc/sphinx.conf
       
    5. 生成字典
        因为用到中文分词,需要生成字典,去安装目录,比如我的是 /home/changyou/mmseg.3.0b3/data/
        #mmseg -u unigram.txt 该命令执行后,将会产生一个名为unigram.txt.uni的文件,将该文件改名为uni.lib,完成词典的构造。
        然后,在/Data/apps/sphinx/var/下建立文件夹 dict,然后把uni.lib放进去
       
    6. 配置
        sphinx.conf 文件中需要对charset_dictpath指定uni.lib的路径/Data/apps/sphinx/var/dict/
        还有连接mysql的信息,这个不用说了罢。
        这里有个参数对于中文用户要注意一下:
        charset_type
        字符集编码类型。可选选项,默认为“sbcs”。已知的值包括“sbcs”和“utf-8”。
        对于中文用户,可选的值还可以有“zh_cn.utf-8 ”和“zh_cn.gbk”。当设置charset_type值为上面的两种时,系统默认您开启了中文分词特性。
        但是我设置了zh_cn.utf-8,报错说“unknown charset type 'zh_cn.utf-8'”,不知道为什么。。。。。

    7. 运行
         # /Data/apps/sphinx/bin/indexer
         启动索引服务时,如果报下面的错:
         error while loading shared libraries: libmysqlclient.so.15: cannot open shared object file: No such file or directory
         原因应该是因为mysql的lib文件不在系统的lib搜索路径上导致的。
         运行命令,解决:
         # ln -s /Data/apps/mysql/lib/mysql/libmysqlclient.so.15 /usr/lib/libmysqlclient.so.15
         
    8. 导入测试数据
         # mysql -uroot -p test < /Data/apps/sphinx/etc/example.sql
         这里千万注意,mysql编码一定要为UTF-8 !!!
        
    9. 测试建立索引
         #indexer --all
         出错,Coreseek Full Text Server 3.1
         Copyright (c) 2006-2008 coreseek.com
         FATAL: no readable config file (looked in /usr/local/sphinx/etc/csft.conf, ./csft.conf)
         这是因为 Coreseek 默认要去读 csft.conf,所以要复制一份
         # cp /Data/apps/sphinx/etc/sphinx.conf /Data/apps/sphinx/bin/csft.conf
         ( 或者,也可以指定conf文件,#indexer --config /Data/apps/sphinx/etc/sphinx.conf --all  这里我没有指定,所以用了2个conf文件,很不靠谱)

    10. 然后继续运行 #indexer --all ,应该会看到如下输出:
            Coreseek Full Text Server 2.1
            Copyright (c) 2006-2008 coreseek.com
            using config file '/usr/local/etc/csft.conf'...
            indexing index 'test1'...
            collected 5 docs, 0.0 MB
            sorted 0.0 Mhits, 100.0% done
            total 5 docs, 230 bytes
            total 0.146 sec, 1577.50 bytes/sec, 34.29 docs/sec
            indexing index 'test1stemmed'...
            collected 5 docs, 0.0 MB
            sorted 0.0 Mhits, 100.0% done
            total 5 docs, 230 bytes
            total 0.011 sec, 21879.74 bytes/sec, 475.65 docs/sec

    11. 测试全文检索
        # search doc     应该会看到如下输出:
            Coreseek Full Text Server 3.1
             Copyright (c) 2006-2008 coreseek.com
            using config file './csft.conf'...
            index 'test1': query 'doc ': returned 2 matches of 2 total in 0.000 sec
            
            displaying matches:
            1. document=3, weight=1, group_id=2, date_added=Sat Aug 22 03:54:19 2009
                    id=3
                    group_id=2
                    group_id2=7
                    date_added=2009-08-22 03:54:19
                    title=another doc
                    content=this is another group
            2. document=4, weight=1, group_id=2, date_added=Sat Aug 22 03:54:19 2009
                    id=4
                    group_id=2
                    group_id2=8
                    date_added=2009-08-22 03:54:19
                    title=doc number four
                    content=this is to test groups
            words:
            1. 'doc': 2 documents, 2 hits
            index 'test1stemmed': query 'doc ': returned 2 matches of 2 total in 0.000 sec
            displaying matches:
            1. document=3, weight=1, group_id=2, date_added=Sat Aug 22 03:54:19 2009
                    id=3
                    group_id=2
                    group_id2=7
                    date_added=2009-08-22 03:54:19
                    title=another doc
                    content=this is another group
            2. document=4, weight=1, group_id=2, date_added=Sat Aug 22 03:54:19 2009
                    id=4
                    group_id=2
                    group_id2=8
                    date_added=2009-08-22 03:54:19
                    title=doc number four
                    content=this is to test groups
            words:

            1. 'doc': 2 documents, 2 hits
    12. 启动searchd进程
         # searchd

    PHP接口在源安装包下面的api/下,可以调用测试,很好用,明天继续研究!

    接上一回,调用sphinx,我们先插入一个中文的数据:
    INSERT INTO `test`.`documents` (`id` ,`group_id` ,`group_id2` ,`date_added` ,title` ,`content`)VALUES (NULL , '3', '9', NOW( ) ,'sphinx中文搜索','Sphinx是一个基于SQL的全文检索引擎,可以结合MySQL,PostgreSQL做全文搜索,它可以提供比数据库本身更专业的搜索功能,使得应用程序更容易实现专业化的全文检索。Sphinx特别为一些脚本语言设计搜索API接口,如 PHP,Python,Perl,Ruby等,同时为 MySQL也设计了一个存储引擎插件');

    因为有新数据,所以要重建索引(关于这个问题,以后遇到再研究,如果每天有新数据都要重建索引,很不靠谱)
    先kill searchd进程,运行:
    # searchd --stop    然后
    # indexer --all

    1.调用sphinx:
       一是通过Sphinx官方提供的API接口(接口有Python,Java,Php三种版本)
       二是通过安装SphinxSE(具体见1.2部分),然后创建一个中介sphinxSE类型的表,再通过执行特定的SQL语句实现。
    现在,我们用API接口,在sphinx安装目录有一个API目录,里面有三个PHP文件:test.php,test2.php和 sphinxapi.php。 sphinxapi.php是sphinx调用接口封装文件,test.php是一个在命令行下执行的查询例子文件,test2.php是一个生成摘要的例子文件。
    运行:
    # php /home/changyou/csft-3.1/api/test.php -i test1 doc
    返回结果:
    Query 'doc ' retrieved 2 of 2 matches in 0.000 sec.
    Query stats:  'doc' found 2 times in 2 documents
    Matches:
    1. doc_id=3, weight=100, group_id=2, date_added=2009-08-22 03:54:19
    2. doc_id=4, weight=100, group_id=2, date_added=2009-08-22 03:54:19

    注意:这里,如果不输入参数 -i test1 doc ,那test.php就不会知道你要查那个索引并且搜索什么字句。
    所以,如果想引入生产环境中,我们需要手动修改一下test.php

    a.  注释掉10行-43行,
    b.  然后添加:$search_info = array("1" => "-i", "2" => "test1", "3" => "$keyword");
    c.  foreach ( $search_info as $arg ) 替换原来的foreach
    d.  自己定义下$keyword="设计",记得把文件另存为utf-8
    e.   然后,运行:     # php /home/changyou/csft-3.1/api/test.php
       Query '(乱码)' retrieved 1 of 1 matches in 0.000 sec.
       Query stats:
        '(乱码)' found 8 times in 1 documents
    Matches:
    1. doc_id=5, weight=2, group_id=3, date_added=2009-08-26 20:18:33

    哈哈,OK啦!可以将sphinx文件封装好,就可以用与生产环境了。

    从上面可以看出Query并不能全部取得我们想要的记录内容,比如说Title,Contents字段就没有取出来,根据官方的说明是sphinx 并没有连到mysql去取记录,只是根据它自己的索引内容进行计算,因此如果想用sphinxAPI去取得我们想要的记录,还必须将Query的结果为依据去查询MySQL才可以得到最终我们想要的结果集。

    2.搜索全文时的摘要,高亮显示。
    假设我要搜索关键词"test",通过sphinx可以取到搜索结果,在显示搜索结果时,我希望将含有"test"的进行红色或加粗显示,同时,我不希望全部都显示出来,只需要显示一段摘要,就象google或百度那样,搜出来的结果不是全篇显示,只是部分显示,这个就是摘要的作用。
    以test2.php中为例,可以利用BuildExcerpts方法可以实现摘要的功能。具体可以看看test2.php的代码。这里不说了。

    3.后记
    从网上看到,还可以用SphinxSE方式调用Sphinx。但问题是,我安装的时候,不知道为什么没有安装SphinxSE引擎,在mysql 里用mysql> show engine; 查看。可能是我没有直接编译sphinx然后打2个中文补丁吧,而是用了官网推荐的中文搜索安装包。从索引得到ID号,然后再去查询数据库,也可以实现中文搜索的效果,但是具体效率怎么样就不知道了。
    最后,在sphinx配置文件里,如要用自己的数据,需要修改源数据,这一项:sql_query = \SELECT id, group_id, UNIX_TIMESTAMP(date_added) AS date_added, title, content \ FROM documents;
    让他自己抓取合适你数据结构的语句即可。

    参考:http://blog.c1gstudio.com/archives/722
            http://www.zhengjinjun.com/index.php/2009/06/28/sphinxmysql%E4%B8%AD%E6%96%87%E5%88%86%E8%AF%8D%E5%AE%89%E8%A3%85-%E5%AE%9E%E7%8E%B0%E4%B8%AD%E6%96%87%E5%85%A8%E6%96%87%E6%90%9C%E7%B4%A2/
            http://www.htmldata.cn/?p=171

     

  • 2009-08-21

    linux 安装Mysql - [mysql]

    很简单,但是,草,过程很痛苦,因为少做一步,最后真是要骂街了。

    # useradd mysql

    # tar zxvf mysql-5.0.56.tar.gz  //解压
    # cd /home/changyou/
    mysql-5.0.56 
    # ./configure --prefix=/Data/apps/mysql  // 指定安装目录,公司的应用都在这里,怪异
    --without-debug //去除debug模式
    --with-extra-charsets=gb2312 //添加gb2312中文字符支持
    --enable-assembler //使用一些字符函数的汇编版本
    --without-isam //去掉isam表类型支持 现在很少用了 isam表是一种依赖平台的表
    --without-innodb //去掉innodb表支持 innodb是一种支持事务处理的表,适合企业级应用
    --with-pthread //强制使用pthread库(posix线程库)
    --enable-thread-safe-client //以线程方式编译客户端
    --with-client-ldflags=-all-static 
    --with-mysqld-ldflags=-all-static //以纯静态方式编译服务端和客户端

    # make
    # make install
    # scripts/mysql_install_db //生成mysql用户数据库和表文件,草,就是这里!!
    # cp support-files/my-medium.cnf /etc/my.cnf  //copy配置文件,有large,medium,small三个环境下的,根据机器性能选择,如果负荷比较大,可修改里面的一些变量的内存使用值
    # cp support-files/mysql.server /etc/init.d/mysqld  //copy启动的mysqld文件
    # chmod 700 /etc/init.d/mysqld
    # cd /web
    # chmod 750 mysql -R
    # chgrp mysql mysql -R

    # chown mysql mysql/var -R    (如果没有var目录,可以自己建一个,记得权限)
    # cd /web/mysql/libexec
    # cp mysqld mysqld.old
    # strip mysqld
    # chkconfig --add mysqld
    # chkconfig --level 345 mysqld on
    # service mysqld start
    # netstat -atln
    看看有没有3306的端口打开,如果mysqld不能启动,看看/web/mysql/var下的出错日志,一般都是目录权限没有设置好的问题
    # ln -s /web/mysql/bin/mysql /sbin/mysql
    # ln -s /web/mysql/bin/mysqladmin /sbin/mysqladmin
    # mysqladmin -uroot password "youpassword"   //设置root帐户的密码
    # mysql -uroot -p
    # 输入你设置的密码
    mysql>use mysql;
    mysql>delete from user where password=""; #删除用于本机匿名连接的空密码帐号
    mysql>flush privileges;
    mysql>quit


    注意,如果mysql服务启动不了,提示:
    Starting MySQL/etc/init.d/mysqld: line 159: kill: (21755) - No such process
    看看是否是启动脚本的问题。
    编辑mysqld:
    #vi /etc/init.d/mysqld
    找到类似这样一行:
    $bindir/mysqld_safe --datadir=$datadir --pid-file=$server_pid_file $other_args >/dev/null 2>&1 &
    改为(加上参数--user=root):
    $bindir/mysqld_safe --user=root --datadir=$datadir --pid-file=$server_pid_file $other_args >/dev/null 2>&1 &

    然后再试:
    service mysqld start

    Tag:linux Mysql
  • 2009-08-20

    php的调试工具XHProf的安装,运用 - [php]

    分了台新服务器做测试,最近很闲,正好拿来练手,哈哈,先拿XHProf玩吧。调试PHP时,XDebug一直是大众的不二选择,搭配上Webgrind,可以获得不错的效果,但是很耗资源,CPU一会就到100%了。最近看别人的blog,发现了XHProf,于是想体验了一下。安装过程很简单,但也遇到不少挫折,因为新服务器,上面有些东西是运维装好了,所以没有仔细了解。都是些小问题,不过折腾死了。

    1.#wget http://pecl.php.net/get/xhprof-0.9.2.tgz  一开始wget用不了,报错:Resolving dada... failed: Temporary failure in name resolution.查明是DNS解析的原因,然后更改 /etc/resolv.conf,问运维,写上正确的IP。

    2.下载完了,解压 #tar zxf xhprof-0.9.2.tgz  然后,#cd cd xhprof-0.9.2/extension/

    3.然后 #phpize   (一般编译安装的PHP都有,没有去下)

    4.#./configure --with-php-config=/usr/bin/php-config

    5.#make    #make install  #make test    就搞定了

    6.然后  更改php.ini  把下面的加到文件中

    [xhprof]
    extension=xhprof.so
    ;
    ; directory used by default implementation of the iXHProfRuns
    ; interface (namely, the XHProfRuns_Default class) for storing
    ; XHProf runs.
    ;xhprof.output_dir=<这里写你要保存xhp生成log的目录>

    7.搞定啦!!  整个过程最郁闷的是,php.ini中的extend扩展地址没写,还是默认的“./”一直没发现,试了半天都不成功,崩溃了,最后还是抽了根烟才发现,呵呵,烟是好东西啊。

    测试下,

    <?php
    function bar($x) {
      if ($x > 0) {
        bar($x - 1);
      }
    }
    function foo() {
      for ($idx = 0; $idx < 2; $idx++) {
        bar($idx);
        $x = strlen("abc");
      }
    }
    // start profiling
    xhprof_enable();
    // run program
    foo();
    // stop profiler
    $xhprof_data = xhprof_disable();
    // display raw xhprof data for the profiler run
    print_r($xhprof_data);

    ?> 


    最后返回数组,就表示安装好了。具体哪些值是什么意思先别管,因为下面有UI的配置。会很直观!

    8.首先,为了好看,装个Graphviz:
    wget http://www.graphviz.org/pub/graphviz/stable/SOURCES/graphviz-2.24.0.tar.gz
    tar zxf graphviz-2.24.0.tar.gz
    cd graphviz-2.24.0
    ./configure
    make
    make install

    安装完成后,会生成/usr/local/bin/dot文件,你应该确保路径在PATH环境变量里,以便XHProf能找到它。

    9.把上面的测试代码拿过来改改,在最后面,加上几行:

    include_once ("/Data/web/changyou/xhprof_lib/utils/xhprof_lib.php");
    include_once ("/Data/web/changyou/xhprof_lib/utils/xhprof_runs.php");
    $xhprof_runs = new XHProfRuns_Default();
    // Save the run under a namespace "xhprof_foo".
    // **NOTE**:
    // By default save_run() will automatically generate a unique
    // run id for you. [You can override that behavior by passing
    // a run id (optional arg) to the save_run() method instead.]
    //
    $run_id = $xhprof_runs->save_run($xhprof_data, "xhprof_foo");

    echo "<br>---------------<br>".
    "Assuming you have set up the http based UI for <br>".
    "XHProf at some address, you can view run at <br>".
    "http://192.168.5.148/changyou/xhprof_html/index.php?run=$run_id&source=xhprof_foo<br>".
    "---------------<br>";

    ?>

    然后,好了,运行那个打印出来的URL,OK啦!看看效果,如果你安装了Graphviz,还会有华丽的大图噢


    Tag:php linux