<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>潘少宁的博客 &#187; PHP开发</title>
	<atom:link href="http://www.gosoa.com.cn/category/php%e5%bc%80%e5%8f%91/feed" rel="self" type="application/rss+xml" />
	<link>http://www.gosoa.com.cn</link>
	<description>专注于高性能LAMP架构分析与实践</description>
	<lastBuildDate>Mon, 30 Apr 2012 09:24:04 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>关于memcache分布式一致性hash</title>
		<link>http://www.gosoa.com.cn/%e5%85%b3%e4%ba%8ememcache%e5%88%86%e5%b8%83%e5%bc%8f%e4%b8%80%e8%87%b4%e6%80%a7hash</link>
		<comments>http://www.gosoa.com.cn/%e5%85%b3%e4%ba%8ememcache%e5%88%86%e5%b8%83%e5%bc%8f%e4%b8%80%e8%87%b4%e6%80%a7hash#comments</comments>
		<pubDate>Mon, 30 Apr 2012 08:56:24 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP开发]]></category>
		<category><![CDATA[Memcache]]></category>
		<category><![CDATA[一致性hash]]></category>
		<category><![CDATA[一致性哈希]]></category>
		<category><![CDATA[分布式]]></category>

		<guid isPermaLink="false">http://www.gosoa.com.cn/?p=647</guid>
		<description><![CDATA[consistent hashing 算法早在 1997 年就在论文 Consistent hashing and random trees 中被提出，目前在 cache 系统中应用越来越广泛； 1 基本场景 比如你有 N 个 cache 服务器（后面简称 cache ），那么如何将一个对象 object 映射到 N 个 cache 上呢，你很可能会采用类似下面的通用方法计算 object 的 hash 值，然后均匀的映射到到 N 个 cache ； hash(object)%N 一切都运行正常，再考虑如下的两种情况； 1 一个 cache 服务器 m down 掉了（在实际应用中必须要考虑这种情况），这样所有映射到 cache m 的对象都会失效，怎么办，需要把 cache m 从 cache 中移除，这时候 cache 是 N-1 台，映射公式变成了 hash(object)%(N-1) ； 2 由于访问加重，需要添加 cache ，这时候 cache 是 N+1 台，映射公式变成了 hash(object)%(N+1) ； 1 和 2 意味着什么？这意味着突然之间几乎所有的 cache 都失效了。对于服务器而言，这是一场灾难，洪水般的访问都会直接冲向后台服务器； 再来考虑第三个问题，由于硬件能力越来越强，你可能想让后面添加的节点多做点活，显然上面的 hash 算法也做不到。 有什么方法可以改变这个状况呢，这就是 consistent hashing&#8230; 2 hash 算法和单调性 Hash 算法的一个衡量指标是单调性（ Monotonicity ），定义如下： 单调性是指如果已经有一些内容通过哈希分派到了相应的缓冲中，又有新的缓冲加入到系统中。哈希的结果应能够保证原有已分配的内容可以被映射到新的缓冲中去，而不会被映射到旧的缓冲集合中的其他缓冲区。 容易看到，上面的简单 hash 算法 hash(object)%N 难以满足单调性要求。 3 consistent hashing 算法的原理 consistent hashing 是一种 hash 算法，简单的说，在移除 / 添加一个 cache 时，它能够尽可能小的改变已存在 key 映射关系，尽可能的满足单调性的要求。 下面就来按照 5 个步骤简单讲讲 consistent hashing 算法的基本原理。 3.1 环形hash 空间 考虑通常的 hash 算法都是将 value 映射到一个 32 为的 key 值，也即是 0~2^32-1 次方的数值空间；我们可以将这个空间想象成一个首（ 0 ）尾（ 2^32-1 ）相接的圆环，如下面图 1 所示的那样。   图 1 环形 hash 空间 3.2 把对象映射到hash 空间 接下来考虑 4 个对象 object1~object4 ，通过 hash 函数计算出的 hash 值 key 在环上的分布如图 2 所示。 hash(object1) = key1; … … hash(object4) = key4;   图 2 4 个对象的 key 值分布 3.3 把cache 映射到hash 空间 Consistent hashing 的基本思想就是将对象和 cache 都映射到同一个 hash 数值空间中，并且使用相同的hash 算法。 假设当前有 A,B 和 C 共 3 台 cache ，那么其映射结果将如图 3 所示，他们在 hash 空间中，以对应的 hash值排列。 hash(cache A) = [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: left;" align="center">consistent hashing 算法早在 1997 年就在论文 <strong><a href="http://portal.acm.org/citation.cfm?id=258660" target="_blank">Consistent hashing and random trees</a> </strong>中被提出，目前在 cache 系统中应用越来越广泛；</p>
<h2>1 基本场景</h2>
<p>比如你有 N 个 cache 服务器（后面简称 cache ），那么如何将一个对象 object 映射到 N 个 cache 上呢，你很可能会采用类似下面的通用方法计算 object 的 hash 值，然后均匀的映射到到 N 个 cache ；</p>
<p>hash(object)%N</p>
<p>一切都运行正常，再考虑如下的两种情况；</p>
<p>1 一个 cache 服务器 m down 掉了（在实际应用中必须要考虑这种情况），这样所有映射到 cache m 的对象都会失效，怎么办，需要把 cache m 从 cache 中移除，这时候 cache 是 N-1 台，映射公式变成了 hash(object)%(N-1) ；</p>
<p>2 由于访问加重，需要添加 cache ，这时候 cache 是 N+1 台，映射公式变成了 hash(object)%(N+1) ；</p>
<p>1 和 2 意味着什么？这意味着突然之间几乎所有的 cache 都失效了。对于服务器而言，这是一场灾难，洪水般的访问都会直接冲向后台服务器；</p>
<p>再来考虑第三个问题，由于硬件能力越来越强，你可能想让后面添加的节点多做点活，显然上面的 hash 算法也做不到。</p>
<p>有什么方法可以改变这个状况呢，这就是 consistent hashing&#8230;</p>
<h2>2 hash 算法和单调性</h2>
<p>Hash 算法的一个衡量指标是单调性（ Monotonicity ），定义如下：</p>
<p>单调性是指如果已经有一些内容通过哈希分派到了相应的缓冲中，又有新的缓冲加入到系统中。哈希的结果应能够保证原有已分配的内容可以被映射到新的缓冲中去，而不会被映射到旧的缓冲集合中的其他缓冲区。</p>
<p>容易看到，上面的简单 hash 算法 hash(object)%N 难以满足单调性要求。</p>
<h2>3 consistent hashing 算法的原理</h2>
<p>consistent hashing 是一种 hash 算法，简单的说，在移除 / 添加一个 cache 时，它能够尽可能小的改变已存在 key 映射关系，尽可能的满足单调性的要求。</p>
<p>下面就来按照 5 个步骤简单讲讲 consistent hashing 算法的基本原理。</p>
<h3>3.1 环形hash 空间</h3>
<p>考虑通常的 hash 算法都是将 value 映射到一个 32 为的 key 值，也即是 0~2^32-1 次方的数值空间；我们可以将这个空间想象成一个首（ 0 ）尾（ 2^32-1 ）相接的圆环，如下面图 1 所示的那样。</p>
<p align="center"> <img class="alignnone size-full wp-image-648" title="1" src="http://scofield-wordpress.stor.sinaapp.com/uploads/2012/04/1.jpg" alt="" width="91" height="104" /></p>
<p align="center">图 1 环形 hash 空间</p>
<h3>3.2 把对象映射到hash 空间</h3>
<p>接下来考虑 4 个对象 object1~object4 ，通过 hash 函数计算出的 hash 值 key 在环上的分布如图 2 所示。</p>
<p>hash(object1) = key1;</p>
<p>… …</p>
<p>hash(object4) = key4;</p>
<p align="center"> <img class="alignnone size-full wp-image-649" title="2" src="http://scofield-wordpress.stor.sinaapp.com/uploads/2012/04/2.jpg" alt="" width="234" height="253" data-pinit="registered" /></p>
<p align="center">图 2 4 个对象的 key 值分布</p>
<h3>3.3 把cache 映射到hash 空间</h3>
<p>Consistent hashing 的基本思想就是将对象和 cache 都映射到同一个 hash 数值空间中，并且使用相同的hash 算法。</p>
<p>假设当前有 A,B 和 C 共 3 台 cache ，那么其映射结果将如图 3 所示，他们在 hash 空间中，以对应的 hash值排列。</p>
<p>hash(cache A) = key A;</p>
<p>… …</p>
<p>hash(cache C) = key C;</p>
<p align="center"> <img class="alignnone size-full wp-image-650" title="3" src="http://scofield-wordpress.stor.sinaapp.com/uploads/2012/04/3.jpg" alt="" width="283" height="253" data-pinit="registered" /></p>
<p align="center">图 3 cache 和对象的 key 值分布</p>
<p>说到这里，顺便提一下 cache 的 hash 计算，一般的方法可以使用 cache 机器的 IP 地址或者机器名作为hash 输入。</p>
<h3>3.4 把对象映射到cache</h3>
<p>现在 cache 和对象都已经通过同一个 hash 算法映射到 hash 数值空间中了，接下来要考虑的就是如何将对象映射到 cache 上面了。</p>
<p>在这个环形空间中，如果沿着顺时针方向从对象的 key 值出发，直到遇见一个 cache ，那么就将该对象存储在这个 cache 上，因为对象和 cache 的 hash 值是固定的，因此这个 cache 必然是唯一和确定的。这样不就找到了对象和 cache 的映射方法了吗？！</p>
<p>依然继续上面的例子（参见图 3 ），那么根据上面的方法，对象 object1 将被存储到 cache A 上； object2和 object3 对应到 cache C ； object4 对应到 cache B ；</p>
<h3>3.5 考察cache 的变动</h3>
<p>前面讲过，通过 hash 然后求余的方法带来的最大问题就在于不能满足单调性，当 cache 有所变动时，cache 会失效，进而对后台服务器造成巨大的冲击，现在就来分析分析 consistent hashing 算法。</p>
<p><strong>3.5.1 </strong><strong>移除 cache</strong></p>
<p>考虑假设 cache B 挂掉了，根据上面讲到的映射方法，这时受影响的将仅是那些沿 cache B 逆时针遍历直到下一个 cache （ cache C ）之间的对象，也即是本来映射到 cache B 上的那些对象。</p>
<p>因此这里仅需要变动对象 object4 ，将其重新映射到 cache C 上即可；参见图 4 。</p>
<p align="center"> <img class="alignnone size-full wp-image-651" title="4" src="http://scofield-wordpress.stor.sinaapp.com/uploads/2012/04/4.jpg" alt="" width="283" height="253" data-pinit="registered" /></p>
<p align="center">图 4 Cache B 被移除后的 cache 映射</p>
<p><strong>3.5.2 </strong><strong>添加 cache</strong></p>
<p>再考虑添加一台新的 cache D 的情况，假设在这个环形 hash 空间中， cache D 被映射在对象 object2 和object3 之间。这时受影响的将仅是那些沿 cache D 逆时针遍历直到下一个 cache （ cache B ）之间的对象（它们是也本来映射到 cache C 上对象的一部分），将这些对象重新映射到 cache D 上即可。</p>
<p>&nbsp;</p>
<p>因此这里仅需要变动对象 object2 ，将其重新映射到 cache D 上；参见图 5 。</p>
<p align="center"><img class="alignnone size-full wp-image-652" title="5" src="http://scofield-wordpress.stor.sinaapp.com/uploads/2012/04/5.jpg" alt="" width="283" height="253" data-pinit="registered" /></p>
<p align="center">图 5 添加 cache D 后的映射关系</p>
<h2>4 虚拟节点</h2>
<p>考量 Hash 算法的另一个指标是平衡性 (Balance) ，定义如下：</p>
<p>平衡性</p>
<p>平衡性是指哈希的结果能够尽可能分布到所有的缓冲中去，这样可以使得所有的缓冲空间都得到利用。</p>
<p>hash 算法并不是保证绝对的平衡，如果 cache 较少的话，对象并不能被均匀的映射到 cache 上，比如在上面的例子中，仅部署 cache A 和 cache C 的情况下，在 4 个对象中， cache A 仅存储了 object1 ，而 cache C 则存储了 object2 、 object3 和 object4 ；分布是很不均衡的。</p>
<p>为了解决这种情况， consistent hashing 引入了“虚拟节点”的概念，它可以如下定义：</p>
<p>“虚拟节点”（ virtual node ）是实际节点在 hash 空间的复制品（ replica ），一实际个节点对应了若干个“虚拟节点”，这个对应个数也成为“复制个数”，“虚拟节点”在 hash 空间中以 hash 值排列。</p>
<p>仍以仅部署 cache A 和 cache C 的情况为例，在图 4 中我们已经看到， cache 分布并不均匀。现在我们引入虚拟节点，并设置“复制个数”为 2 ，这就意味着一共会存在 4 个“虚拟节点”， cache A1, cache A2 代表了 cache A ； cache C1, cache C2 代表了 cache C ；假设一种比较理想的情况，参见图 6 。</p>
<p align="center"><img class="alignnone size-full wp-image-653" title="6" src="http://scofield-wordpress.stor.sinaapp.com/uploads/2012/04/6.jpg" alt="" width="283" height="253" data-pinit="registered" /></p>
<p align="center">图 6 引入“虚拟节点”后的映射关系</p>
<p>此时，对象到“虚拟节点”的映射关系为：</p>
<p>objec1-&gt;cache A2 ； objec2-&gt;cache A1 ； objec3-&gt;cache C1 ； objec4-&gt;cache C2 ；</p>
<p>因此对象 object1 和 object2 都被映射到了 cache A 上，而 object3 和 object4 映射到了 cache C 上；平衡性有了很大提高。</p>
<p>引入“虚拟节点”后，映射关系就从 { 对象 -&gt; 节点 } 转换到了 { 对象 -&gt; 虚拟节点 } 。查询物体所在 cache时的映射关系如图 7 所示。</p>
<p align="center"><img class="alignnone size-medium wp-image-654" title="7" src="http://scofield-wordpress.stor.sinaapp.com/uploads/2012/04/7-300x131.jpg" alt="" width="300" height="131" data-pinit="registered" /></p>
<p align="center">图 7 查询对象所在 cache</p>
<p>“虚拟节点”的 hash 计算可以采用对应节点的 IP 地址加数字后缀的方式。例如假设 cache A 的 IP 地址为202.168.14.241 。</p>
<p>引入“虚拟节点”前，计算 cache A 的 hash 值：</p>
<p>Hash(“202.168.14.241”);</p>
<p>引入“虚拟节点”后，计算“虚拟节”点 cache A1 和 cache A2 的 hash 值：</p>
<p>Hash(“202.168.14.241#1”);  // cache A1</p>
<p>Hash(“202.168.14.241#2”);  // cache A2</p>
<p>&nbsp;</p>
<p><strong>而在PHP使用pecl::memcache  的时候，客户端也已经实现了 consistent 算法。需要修改如下参数。</strong></p>
<p>memcache.hash_strategy=consistent<br />
memcache.hash_function=crc32</p>
<p>参考: pecl::memcache的配置参数，<a href="http://www.php.net/manual/en/memcache.ini.php">http://www.php.net/manual/en/memcache.ini.php</a></p>
<p>这里有一篇关于pecl::memcache的测试 <a href="http://www.surfchen.org/archives/348">http://www.surfchen.org/archives/348</a></p>
<p>&nbsp;</p>
<p>转载：<a href="http://blog.csdn.net/sparkliang/article/details/5279393">http://blog.csdn.net/sparkliang/article/details/5279393</a></p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gosoa.com.cn/%e5%85%b3%e4%ba%8ememcache%e5%88%86%e5%b8%83%e5%bc%8f%e4%b8%80%e8%87%b4%e6%80%a7hash/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>http_build_query 的一个问题</title>
		<link>http://www.gosoa.com.cn/http_build_query-%e7%9a%84%e4%b8%80%e4%b8%aa%e9%97%ae%e9%a2%98</link>
		<comments>http://www.gosoa.com.cn/http_build_query-%e7%9a%84%e4%b8%80%e4%b8%aa%e9%97%ae%e9%a2%98#comments</comments>
		<pubDate>Mon, 06 Feb 2012 10:25:01 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP开发]]></category>
		<category><![CDATA[http_build_query]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.gosoa.com.cn/?p=628</guid>
		<description><![CDATA[当我们使用CURL来post数据的时候，需要设置post的数据 curl_setopt($c, CURLOPT_POSTFIELDS, $post_data); 假如这里的$data是 $data = array( 'name'=>'scofield', 'time'=>'2012-2-3' ) 接下来，需要先将$data变成字符串 $post_data = http_build_query($data); 而采用 http_build_query 转换后再 curl_setopt($c, CURLOPT_POSTFIELDS, $post_data); 看起来没有什么问题。但在实际操作中，$post_data 并没有被post过去。于是，自己写了个转换的方法后就OK了。 function getStr($array,$Separator='&#038;') { if (empty($array)) return; if (!is_array($array)) { return $array; } $returnStr = ''; foreach ($array as $key => $val) { $temp = ''; if (is_array($val)) { for ($i = 0; [...]]]></description>
			<content:encoded><![CDATA[<p>当我们使用CURL来post数据的时候，需要设置post的数据<br />
curl_setopt($c, CURLOPT_POSTFIELDS, $post_data);</p>
<p>假如这里的$data是</p>
<pre name="php">
$data = array(
   'name'=>'scofield',
   'time'=>'2012-2-3'
)
</pre>
<p>接下来，需要先将$data变成字符串<br />
$post_data =  http_build_query($data);<br />
而采用 http_build_query 转换后再<br />
curl_setopt($c, CURLOPT_POSTFIELDS, $post_data); </p>
<p>看起来没有什么问题。但在实际操作中，$post_data 并没有被post过去。于是，自己写了个转换的方法后就OK了。</p>
<pre name="php">
 function getStr($array,$Separator='&#038;') {
        if (empty($array))
            return;
        if (!is_array($array)) {
            return $array;
        }
        $returnStr = '';
        foreach ($array as $key => $val) {
            $temp = '';
            if (is_array($val)) {
                for ($i = 0; $i < count($val); $i++) {
                    $returnStr .= $key . '[' . $i . ']' . '=' . $val[$i] . $Separator;
                }
            } else {
                $returnStr.= $key . '=' . $val . $Separator;
            }
        }
        $returnStr = substr(trim($returnStr), 0, -1);
        return $returnStr;
    }
</pre>
<p></p>
<p><b>感谢 黄斌-huangbin  童鞋的测试   http_build_query($data,"","&#038;");  即可，无需自己写方法解析了。</b></p>
<p></p>
]]></content:encoded>
			<wfw:commentRss>http://www.gosoa.com.cn/http_build_query-%e7%9a%84%e4%b8%80%e4%b8%aa%e9%97%ae%e9%a2%98/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>一个有意思的日期逻辑处理</title>
		<link>http://www.gosoa.com.cn/%e4%b8%80%e4%b8%aa%e6%9c%89%e6%84%8f%e6%80%9d%e7%9a%84%e6%97%a5%e6%9c%9f%e9%80%bb%e8%be%91%e5%a4%84%e7%90%86</link>
		<comments>http://www.gosoa.com.cn/%e4%b8%80%e4%b8%aa%e6%9c%89%e6%84%8f%e6%80%9d%e7%9a%84%e6%97%a5%e6%9c%9f%e9%80%bb%e8%be%91%e5%a4%84%e7%90%86#comments</comments>
		<pubDate>Tue, 19 Jul 2011 09:39:57 +0000</pubDate>
		<dc:creator>scofield</dc:creator>
				<category><![CDATA[PHP开发]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.gosoa.com.cn/?p=617</guid>
		<description><![CDATA[今天处理了一个很小的问题。
需求是这样的，从周一到周日只能看到上周一到上周日的数据。
这里直接从数据库里根据 date 字段查询 范围即可。
但需要PHP生成 开始日期和结束日期。

最开始，我直接这么处理。
<pre name="code" class="php">
$start_date = date('Y-m-d' , strtotime("-2 week monday"));
$end_date = date('Y-m-d' , strtotime("$start_date +6 day"));
</pre>
假如日期是 2011-07-19，$start_date= 2011-07-11  这样处理没有问题。
如果日期是  2011-07-18 ，$start_date 则会等于 2011-07-04，还活在上周。]]></description>
			<content:encoded><![CDATA[<p>今天处理了一个很小的问题。<br />
需求是这样的，从周一到周日只能看到上周一到上周日的数据。<br />
这里直接从数据库里根据 date 字段查询 范围即可。<br />
但需要PHP生成 开始日期和结束日期。</p>
<p>最开始，我直接这么处理。</p>
<pre name="code" class="php">
$start_date = date('Y-m-d' , strtotime("-2 week monday"));
$end_date = date('Y-m-d' , strtotime("$start_date +6 day"));
</pre>
<p>假如日期是 2011-07-19，$start_date= 2011-07-11  这样处理没有问题。<br />
如果日期是  2011-07-18 ，$start_date 则会等于 2011-07-04，还活在上周。</p>
<p>于是换了种方法</p>
<pre name="code" class="php">
$getWeekDay = date("w");
$startDay = date("Y-m-d", mktime(0, 0, 0, date("m"), date("d") - $getWeekDay + 1 - 7, date("Y")));
$endDay = date("Y-m-d", strtotime("+6 day $startDay"));
</pre>
<p>假如日期是 2011-07-19，$start_date= 2011-07-11  这样处理没有问题，和我们期望的一样。<br />
如果日期是 2011-07-24，我们期望的  $start_date 是 2011-07-11，但实际返回的是 2011-07-18。</p>
<p>不得已，我再改了下方法</p>
<pre name="code" class="php">
$getWeekDay = date("N") ;
$startDay = date("Y-m-d", mktime(0, 0, 0, date("m"), date("d") - $getWeekDay + 1 - 7, date("Y")));
$endDay = date("Y-m-d", strtotime("+6 day $startDay"));
</pre>
<p>这下就OK 了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gosoa.com.cn/%e4%b8%80%e4%b8%aa%e6%9c%89%e6%84%8f%e6%80%9d%e7%9a%84%e6%97%a5%e6%9c%9f%e9%80%bb%e8%be%91%e5%a4%84%e7%90%86/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>PHP用CURL伪造IP和来源</title>
		<link>http://www.gosoa.com.cn/php%e7%94%a8curl%e4%bc%aa%e9%80%a0ip%e5%92%8c%e6%9d%a5%e6%ba%90</link>
		<comments>http://www.gosoa.com.cn/php%e7%94%a8curl%e4%bc%aa%e9%80%a0ip%e5%92%8c%e6%9d%a5%e6%ba%90#comments</comments>
		<pubDate>Tue, 19 Jul 2011 09:09:02 +0000</pubDate>
		<dc:creator>scofield</dc:creator>
				<category><![CDATA[PHP开发]]></category>
		<category><![CDATA[CURL]]></category>

		<guid isPermaLink="false">http://www.gosoa.com.cn/?p=614</guid>
		<description><![CDATA[以前没有这么搞过。

今天群里一个朋友在问这个问题。

查了下，CURL确实很强悍的可以伪造IP和来源。

1.php 请求 2.php 。

1.php代码：]]></description>
			<content:encoded><![CDATA[<p>以前没有这么搞过。</p>
<p>今天群里一个朋友在问这个问题。</p>
<p>查了下，CURL确实很强悍的可以伪造IP和来源。</p>
<p>1.php 请求 2.php 。</p>
<p>1.php代码：</p>
<pre name="code" class="php">

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://localhost/2.php");
curl_setopt($ch, CURLOPT_HTTPHEADER, array('X-FORWARDED-FOR:8.8.8.8', 'CLIENT-IP:8.8.8.8'));  //构造IP
curl_setopt($ch, CURLOPT_REFERER, "http://www.gosoa.com.cn/ ");   //构造来路
curl_setopt($ch, CURLOPT_HEADER, 1);
$out = curl_exec($ch);
curl_close($ch);
</pre>
<p>2.php代码如下：</p>
<pre name="code" class="php">

function getClientIp() {
    if (!empty($_SERVER["HTTP_CLIENT_IP"]))
        $ip = $_SERVER["HTTP_CLIENT_IP"];
    else if (!empty($_SERVER["HTTP_X_FORWARDED_FOR"]))
        $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
    else if (!empty($_SERVER["REMOTE_ADDR"]))
        $ip = $_SERVER["REMOTE_ADDR"];
    else
        $ip = "err";
    return $ip;
}

echo "IP: " . getClientIp() . "";
echo "referer: " . $_SERVER["HTTP_REFERER"];
</pre>
<p>伪造成功，这是不是给“刷票”的朋友提供了很好的换IP的方案！！<br />
哈哈。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gosoa.com.cn/php%e7%94%a8curl%e4%bc%aa%e9%80%a0ip%e5%92%8c%e6%9d%a5%e6%ba%90/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>优化PHP代码的40条建议[转]</title>
		<link>http://www.gosoa.com.cn/%e4%bc%98%e5%8c%96php%e4%bb%a3%e7%a0%81%e7%9a%8440%e6%9d%a1%e5%bb%ba%e8%ae%ae%e8%bd%ac</link>
		<comments>http://www.gosoa.com.cn/%e4%bc%98%e5%8c%96php%e4%bb%a3%e7%a0%81%e7%9a%8440%e6%9d%a1%e5%bb%ba%e8%ae%ae%e8%bd%ac#comments</comments>
		<pubDate>Fri, 01 Jul 2011 09:41:53 +0000</pubDate>
		<dc:creator>scofield</dc:creator>
				<category><![CDATA[PHP开发]]></category>
		<category><![CDATA[PHP优化]]></category>

		<guid isPermaLink="false">http://www.gosoa.com.cn/?p=603</guid>
		<description><![CDATA[1.如果一个方法可静态化，就对它做静态声明。速率可提升至4倍。

2.echo 比 print 快。

3.使用echo的多重参数（译注：指用逗号而不是句点）代替字符串连接。

4.在执行for循环之前确定最大循环数，不要每循环一次都计算最大值。

5.注销那些不用的变量尤其是大数组，以便释放内存。

6.尽量避免使用__get，__set，__autoload。]]></description>
			<content:encoded><![CDATA[<p>1.如果一个方法可静态化，就对它做静态声明。速率可提升至4倍。</p>
<p>2.echo 比 print 快。</p>
<p>3.使用echo的多重参数（译注：指用逗号而不是句点）代替字符串连接。</p>
<p>4.在执行for循环之前确定最大循环数，不要每循环一次都计算最大值。</p>
<p>5.注销那些不用的变量尤其是大数组，以便释放内存。</p>
<p>6.尽量避免使用__get，__set，__autoload。</p>
<p>7.require_once()代价昂贵。</p>
<p>8.在包含文件时使用完整路径，解析操作系统路径所需的时间会更少。</p>
<p>9.如果你想知道脚本开始执行（译注：即服务器端收到客户端请求）的时刻，使用$_SERVER[‘REQUEST_TIME’]要好于time()。</p>
<p>10.函数代替正则表达式完成相同功能。</p>
<p>11.str_replace函数比preg_replace函数快，但strtr函数的效率是str_replace函数的四倍。</p>
<p>12.如果一个字符串替换函数，可接受数组或字符作为参数，并且参数长度不太长，那么可以考虑额外写一段替换代码，使得每次传递参数是一个字符，而不是只写一行代码接受数组作为查询和替换的参数。</p>
<p>13.使用选择分支语句（译注：即switch case）好于使用多个if，else if语句。</p>
<p>14.用@屏蔽错误消息的做法非常低效。</p>
<p>15.打开apache的mod_deflate模块。</p>
<p>16.数据库连接当使用完毕时应关掉。</p>
<p>17.$row[‘id’]的效率是$row[id]的7倍。</p>
<p>18.错误消息代价昂贵。</p>
<p>19.尽量不要在for循环中使用函数，比如for ($x=0; $x &lt; count($array); $x)每循环一次都会调用count()函数。</p>
<p>20.在方法中递增局部变量，速度是最快的。几乎与在函数中调用局部变量的速度相当。</p>
<p>21.递增一个全局变量要比递增一个局部变量慢2倍。</p>
<p>22.递增一个对象属性（如：$this-&gt;prop++）要比递增一个局部变量慢3倍。</p>
<p>23.递增一个未预定义的局部变量要比递增一个预定义的局部变量慢9至10倍。</p>
<p>24.仅定义一个局部变量而没在函数中调用它，同样会减慢速度（其程度相当于递增一个局部变量）。PHP大概会检查看是否存在全局变量。</p>
<p>25.方法调用看来与类中定义的方法的数量无关，因为我（在测试方法之前和之后都）添加了10个方法，但性能上没有变化。</p>
<p>26.派生类中的方法运行起来要快于在基类中定义的同样的方法。</p>
<p>27.调用带有一个参数的空函数，其花费的时间相当于执行7至8次的局部变量递增操作。类似的方法调用所花费的时间接近于15次的局部变量递增操作。</p>
<p>28.用单引号代替双引号来包含字符串，这样做会更快一些。因为PHP会在双引号包围的字符串中搜寻变量，单引号则不会。当然，只有当你不需要在字符串中包含变量时才可以这么做。</p>
<p>29.输出多个字符串时，用逗号代替句点来分隔字符串，速度更快。注意：只有echo能这么做，它是一种可以把多个字符串当作参数的“函数”（译注：PHP手册中说echo是语言结构，不是真正的函数，故把函数加上了双引号）。</p>
<p>30.Apache解析一个PHP脚本的时间要比解析一个静态HTML页面慢2至10倍。尽量多用静态HTML页面，少用脚本。</p>
<p>31.除非脚本可以缓存，否则每次调用时都会重新编译一次。引入一套PHP缓存机制通常可以提升25%至100%的性能，以免除编译开销。</p>
<p>32.尽量做缓存，可使用memcached。memcached是一款高性能的内存对象缓存系统，可用来加速动态Web应用程序，减轻数据库负载。对运算码 (OP code)的缓存很有用，使得脚本不必为每个请求做重新编译。</p>
<p>33.当操作字符串并需要检验其长度是否满足某种要求时，你想当然地会使用strlen()函数。此函数执行起来相当快，因为它不做任何计算，只返回在zval 结构（C的内置数据结构，用于存储PHP变量）中存储的已知字符串长度。但是，由于strlen()是函数，多多少少会有些慢，因为函数调用会经过诸多步骤，如字母小写化（译注：指函数名小写化，PHP不区分函数名大小写）、哈希查找，会跟随被调用的函数一起执行。在某些情况下，你可以使用isset() 技巧加速执行你的代码。</p>
<p>（举例如下）<br />
if (strlen($foo) &lt; 5) { echo “Foo is too short”; }<br />
（与下面的技巧做比较）<br />
if (!isset($foo)) { echo “Foo is too short”; }</p>
<p>调用isset()恰巧比strlen()快，因为与后者不同的是，isset()作为一种语言结构，意味着它的执行不需要函数查找和字母小写化。也就是说，实际上在检验字符串长度的顶层代码中你没有花太多开销。</p>
<p>34.当执行变量$i的递增或递减时，$i++会比++$i慢一些。这种差异是PHP特有的，并不适用于其他语言，所以请不要修改你的C或Java代码并指望它们能立即变快，没用的。++$i更快是因为它只需要3条指令(opcodes)，$i++则需要4条指令。后置递增实际上会产生一个临时变量，这个临时变量随后被递增。而前置递增直接在原值上递增。这是最优化处理的一种，正如Zend的PHP优化器所作的那样。牢记这个优化处理不失为一个好主意，因为并不是所有的指令优化器都会做同样的优化处理，并且存在大量没有装配指令优化器的互联网服务提供商（ISPs）和服务器。</p>
<p>35.并不是事必面向对象(OOP)，面向对象往往开销很大，每个方法和对象调用都会消耗很多内存。</p>
<p>36.并非要用类实现所有的数据结构，数组也很有用。</p>
<p>37.不要把方法细分得过多，仔细想想你真正打算重用的是哪些代码？</p>
<p>38.当你需要时，你总能把代码分解成方法。</p>
<p>39.尽量采用大量的PHP内置函数。</p>
<p>40.如果在代码中存在大量耗时的函数，你可以考虑用C扩展的方式实现它们。</p>
<p>41.评估检验(profile)你的代码。检验器会告诉你，代码的哪些部分消耗了多少时间。Xdebug调试器包含了检验程序，评估检验总体上可以显示出代码的瓶颈。</p>
<p>42.mod_zip可作为Apache模块，用来即时压缩你的数据，并可让数据传输量降低80%。</p>
<p>原文地址： <a href="http://www.builder.com.cn/2008/0203/728680.shtml">http://www.builder.com.cn/2008/0203/728680.shtml</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.gosoa.com.cn/%e4%bc%98%e5%8c%96php%e4%bb%a3%e7%a0%81%e7%9a%8440%e6%9d%a1%e5%bb%ba%e8%ae%ae%e8%bd%ac/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP几个不常用但很有用的函数</title>
		<link>http://www.gosoa.com.cn/php%e5%87%a0%e4%b8%aa%e4%b8%8d%e5%b8%b8%e7%94%a8%e4%bd%86%e5%be%88%e6%9c%89%e7%94%a8%e7%9a%84%e5%87%bd%e6%95%b0</link>
		<comments>http://www.gosoa.com.cn/php%e5%87%a0%e4%b8%aa%e4%b8%8d%e5%b8%b8%e7%94%a8%e4%bd%86%e5%be%88%e6%9c%89%e7%94%a8%e7%9a%84%e5%87%bd%e6%95%b0#comments</comments>
		<pubDate>Wed, 29 Jun 2011 13:26:43 +0000</pubDate>
		<dc:creator>scofield</dc:creator>
				<category><![CDATA[PHP开发]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.gosoa.com.cn/?p=593</guid>
		<description><![CDATA[glob() 直接print_r(glob(&#8216;*&#8217;)) 看看效果吧。 再  print_r(glob(&#8216;*.PHP&#8217;)) 再看看效果吧。 &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- PHP Filter函数 PHP自带的filter函数。直接可以用来验证email，IP等。也可以用来验证 INPUT等。 具体见这里 http://php.net/manual/en/book.filter.php &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- get_browser() 获得浏览器信息的。 &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- sys_getloadavg() 这个函数只针对linux系统有用。 可以用来监测系统的负载。 其值就是linux的 load average值。]]></description>
			<content:encoded><![CDATA[<ul>
<li><strong>glob()</strong></li>
</ul>
<p>直接print_r(glob(&#8216;*&#8217;)) 看看效果吧。</p>
<p>再  print_r(glob(&#8216;*.PHP&#8217;)) 再看看效果吧。</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<ul>
<li><strong>PHP Filter函数</strong></li>
</ul>
<p><a href="http://php.net/manual/en/book.filter.php" target="_blank">PHP自带的filter函数</a>。直接可以用来验证email，IP等。也可以用来验证 INPUT等。</p>
<p>具体见这里 <a href="http://php.net/manual/en/book.filter.php">http://php.net/manual/en/book.filter.php</a></p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<ul>
<li><strong>get_browser()</strong></li>
</ul>
<p>获得浏览器信息的。</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<ul>
<li><strong>sys_getloadavg()</strong></li>
</ul>
<p>这个函数只针对linux系统有用。</p>
<p>可以用来监测系统的负载。 其值就是linux的 load average值。</p>
<p><strong><br />
</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.gosoa.com.cn/php%e5%87%a0%e4%b8%aa%e4%b8%8d%e5%b8%b8%e7%94%a8%e4%bd%86%e5%be%88%e6%9c%89%e7%94%a8%e7%9a%84%e5%87%bd%e6%95%b0/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>推荐一款开源的flashchart生成柱状图</title>
		<link>http://www.gosoa.com.cn/%e6%8e%a8%e8%8d%90%e4%b8%80%e6%ac%be%e5%bc%80%e6%ba%90%e7%9a%84flashchart%e7%94%9f%e6%88%90%e6%9f%b1%e7%8a%b6%e5%9b%be</link>
		<comments>http://www.gosoa.com.cn/%e6%8e%a8%e8%8d%90%e4%b8%80%e6%ac%be%e5%bc%80%e6%ba%90%e7%9a%84flashchart%e7%94%9f%e6%88%90%e6%9f%b1%e7%8a%b6%e5%9b%be#comments</comments>
		<pubDate>Mon, 27 Jun 2011 10:54:44 +0000</pubDate>
		<dc:creator>scofield</dc:creator>
				<category><![CDATA[PHP开发]]></category>
		<category><![CDATA[flashchart]]></category>
		<category><![CDATA[php生成饼图]]></category>

		<guid isPermaLink="false">http://www.gosoa.com.cn/?p=580</guid>
		<description><![CDATA[最近项目中需要生成类似excel的柱状图、饼图、趋势图等等。。。

网上google了一番，发现了 Open Flash Chart   地址：  http://teethgrinder.co.uk/open-flash-chart-2/ 。

非常好用的一款开源工具。目前最新版是2.0

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

http://ofcgwt.googlecode.com/svn/demo/Demo.html 这里有很多示例可供参考。

不过不太推荐使用 googlecode上的这个示例代码，建议采用官方的示例代码和flash chart 。

flash chart的使用很简单。

如下示例：]]></description>
			<content:encoded><![CDATA[<p>最近项目中需要生成类似excel的柱状图、饼图、趋势图等等。。。</p>
<p>网上google了一番，发现了 Open Flash Chart   地址：  <a href="http://teethgrinder.co.uk/open-flash-chart-2/">http://teethgrinder.co.uk/open-flash-chart-2/</a> 。</p>
<p>非常好用的一款开源工具。目前最新版是2.0</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p><a href="http://ofcgwt.googlecode.com/svn/demo/Demo.html">http://ofcgwt.googlecode.com/svn/demo/Demo.html</a> 这里有很多示例可供参考。</p>
<p>不过不太推荐使用 googlecode上的这个示例代码，建议采用官方的示例代码和flash chart 。</p>
<p>flash chart的使用很简单。</p>
<p>如下示例：</p>
<pre name="code" class="js">//url形式
function embSwfWithUrl(dataurl,divcon){
     var params = {
        "wmode": "transparent",
        "menu": "false",
        "scale": "noScale",
        "allowFullscreen": "false",
        "allowScriptAccess": "always",
        "bgcolor": "#c0c0c0"  //背景
    };
    var flashvars = {
        'data-file' : dataurl
    };
    swfobject.embedSWF("/swf/open-flash-chart.swf?timestamp=" + Math.random(),divcon, "450", "300", "10.0.0", "./swf/expressInstall.swf" ,flashvars,params);
}

embSwfWithUrl('http://xxx.com/xxx.html','swfCon');</pre>
<p>这里的http://xxx.com/xxx.html返回的是相应的json格式的数据。</p>
<p>swfCon是放flash的div容器。</p>
<p>swfobject是开源的js处理flash的类。<a href="http://code.google.com/p/swfobject/">http://code.google.com/p/swfobject/</a></p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>注意下，flash chart 获得数据的方式有两种，</p>
<p>一种是   data-file  一种是 get-data</p>
<p>data-file 正是如上示例，值必须是个 url地址，里面返回的是 json数据。</p>
<p>而get-data的值则是一个函数名称。 函数返回 json 数据。</p>
<p>如下示例：</p>
<pre name="code" class="js">//get-data
function embSwfWithData(divcon,getdataFn){
    var params = {
        "wmode": "transparent",  //窗口模式
        "menu": "false",  //菜单显示
        "scale": "noScale",  //缩放
        "allowFullscreen": "false", //允许全屏
        "allowScriptAccess": "always",  //允许脚本
        "bgcolor": "#c0c0c0"  //背景
    };
var flashVar = {
 "get-data":getdataFn
};
    swfobject.embedSWF("/swf/open-flash-chart.swf?timestamp=" + Math.random(), divcon, "450", "300", "10", "/swf/expressInstall.swf",flashVar  ,params);
}

function getJsonData(){
return 'json data';
}</pre>
<p>这里 “get-data”:getdataFn 需要传递的就是一个函数名称。函数中返回json数据。</p>
<p>还有一点需要注意下，/swf/open-flash-chart.swf?timestamp=+Math.random() .</p>
<p>这里之所以加随机数，是因为有的浏览器在缓存flash后，使其flash参数失效了。加上随机数后，每次浏览器会重新加载flash。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gosoa.com.cn/%e6%8e%a8%e8%8d%90%e4%b8%80%e6%ac%be%e5%bc%80%e6%ba%90%e7%9a%84flashchart%e7%94%9f%e6%88%90%e6%9f%b1%e7%8a%b6%e5%9b%be/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP导出excel</title>
		<link>http://www.gosoa.com.cn/php%e5%af%bc%e5%87%baexcel</link>
		<comments>http://www.gosoa.com.cn/php%e5%af%bc%e5%87%baexcel#comments</comments>
		<pubDate>Mon, 27 Jun 2011 10:23:07 +0000</pubDate>
		<dc:creator>scofield</dc:creator>
				<category><![CDATA[PHP开发]]></category>
		<category><![CDATA[PHPExcel]]></category>
		<category><![CDATA[PHP生成EXcel]]></category>

		<guid isPermaLink="false">http://www.gosoa.com.cn/?p=573</guid>
		<description><![CDATA[最近做一个项目，其中涉及到了数据导成excel的功能。

后来使用了 开源的 PHPExcel  <a href="http://phpexcel.codeplex.com/">http://phpexcel.codeplex.com/</a> 目前最新版是1.7.6

PHPExcel 可以生成 .xls 和 .xlsx （office2007）。其封装的方法很全了。

比如设置 excel的title，keywords,description

获得某个sheet，某个列的数据 等等。

具体的文档，查看这里，<a href="http://phpexcel.codeplex.com/releases/view/45412">http://phpexcel.codeplex.com/releases/view/45412</a> 非常详细。

下面是一段简单的示例。]]></description>
			<content:encoded><![CDATA[<p>最近做一个项目，其中涉及到了数据导成excel的功能。</p>
<p>后来使用了 开源的 PHPExcel  <a href="http://phpexcel.codeplex.com/">http://phpexcel.codeplex.com/</a> 目前最新版是1.7.6</p>
<p>PHPExcel 可以生成 .xls 和 .xlsx （office2007）。其封装的方法很全了。</p>
<p>比如设置 excel的title，keywords,description</p>
<p>获得某个sheet，某个列的数据 等等。</p>
<p>具体的文档，查看这里，<a href="http://phpexcel.codeplex.com/releases/view/45412">http://phpexcel.codeplex.com/releases/view/45412</a> 非常详细。</p>
<p>下面是一段简单的示例。</p>
<pre name="code" class="php">//这里要 include进来 phpexcel类
include ROOT_PATH . 'library/PHPExcel-1.7.6/PHPExcel.PHP';
include ROOT_PATH . 'library/PHPExcel-1.7.6/PHPExcel/Writer/Excel2007.PHP';

class MyExcel {

    public static function makeExcel($title, $data, $excle_name) {
        $exclefile = 'excel/' . date('Y-m-d') . '/' . md5($excle_name) . '.xlsx';

        $Excel = new PHPExcel();
        $Excel-&gt;setActiveSheetIndex(0);
        $Excel-&gt;getSheet()-&gt;setTitle($title);

        $cell_one = $data[0];
        $j = 0;
        foreach ($cell_one as $k =&gt; $v) {
            $Excel-&gt;getSheet()-&gt;setCellValue(self::getCharByNunber($j) . '1', $k);
            $j++;
        }

        $x = 2;
        foreach ($data as $value) {
            $y = 0;
            foreach ($value as $k =&gt; $v) {
                $Excel-&gt;getSheet()-&gt;setCellValue(self::getCharByNunber($y) . $x, $v);
                $y++;
            }
            $x++;
        }

        $objwriter = new PHPExcel_Writer_Excel2007($Excel);
        $objwriter-&gt;save($exclefile);
        TMDebugUtils::debugLog('make ' . $exclefile);
        return $exclefile;
    }

    protected static function getCharByNunber($num) {
        $num = intval($num);
        $arr = array('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',);
        return $arr[$num];
    }

}

//导出用户基本信息
function exportUserBaseInfo() {
    $excelTitle = '用户基本信息';
    $excelFileName = 'userbase';
    $data = array();
    // $rs = ....  这里rs是从db读取的数据
    for ($i = 0; $i &lt; count($rs); $i++) {         $data[$i]['姓名'] = $rs[$i]-&gt;name;
        $data[$i]['年龄'] = intval($rs[$i]-&gt;age);
        $data[$i]['日期'] = $rs[$i]-&gt;date;
    }
    MyExcel::makeExcel($excelTitle, $data, $excelFileName);
}

//导出新闻资讯信息
function exportUserBaseInfo() {
    $excelTitle = '新闻资讯信息';
    $excelFileName = 'news';
    $data = array();
    // $rs = ....  这里rs是从db读取的数据
    for ($i = 0; $i &lt; count($rs); $i++) {         $data[$i]['标题'] = $rs[$i]-&gt;title;
        $data[$i]['作者'] = $rs[$i]-&gt;author;
        $data[$i]['日期'] = $rs[$i]-&gt;date;
        $data[$i]['浏览数'] = floatval($rs[$i]-&gt;view_count);
        $data[$i]['被评论数'] = floatval($rs[$i]-&gt;comment_count);
    }
    MyExcel::makeExcel($excelTitle, $data, $excelFileName);
}

//end</pre>
<p>这里只是简单的生成的xlsx，其他需要读取更复杂的，可以阅读官方的手册，有很详细的说明。</p>
<p>如果不需要保存，直接输出到浏览，如下：</p>
<pre name="code" class="php">//不用保存，直接输出到浏览器
$objwriter = new PHPExcel_Writer_Excel2007($Excel);
        header("Content-Type: application/force-download");
        header("Content-Type: application/octet-stream");
        header("Content-Type: application/download");
        header('Content-Disposition:inline;filename=temp.xlsx');
        header("Content-Transfer-Encoding: binary");
        header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
        header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
        header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
        header("Pragma: no-cache");
        $objwriter-&gt;save('php://output');</pre>
<p>The End</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gosoa.com.cn/php%e5%af%bc%e5%87%baexcel/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>NoSQL &#8211; Redis几个认识误区</title>
		<link>http://www.gosoa.com.cn/nosql-redis%e5%87%a0%e4%b8%aa%e8%ae%a4%e8%af%86%e8%af%af%e5%8c%ba</link>
		<comments>http://www.gosoa.com.cn/nosql-redis%e5%87%a0%e4%b8%aa%e8%ae%a4%e8%af%86%e8%af%af%e5%8c%ba#comments</comments>
		<pubDate>Sat, 15 Jan 2011 10:02:13 +0000</pubDate>
		<dc:creator>scofield</dc:creator>
				<category><![CDATA[PHP开发]]></category>
		<category><![CDATA[Nosql]]></category>
		<category><![CDATA[Redis]]></category>

		<guid isPermaLink="false">http://www.gosoa.com.cn/?p=557</guid>
		<description><![CDATA[转自 http://timyang.net/data/redis-misunderstanding/ 前几天微博发生了一起大的系统故障，很多技术的朋友都比较关心，其中的原因不会超出James Hamilton在On Designing and Deploying Internet-Scale Service(1)概括的那几个范围，James第一条经验“Design for failure”是所有互联网架构成功的一个关键。互联网系统的工程理论其实非常简单，James paper中内容几乎称不上理论，而是多条实践经验分享，每个公司对这些经验的理解及执行力决定了架构成败。 题外话说完，最近又研究了Redis。去年曾做过一个MemcacheDB, Tokyo Tyrant, Redis performance test，到目前为止，这个benchmark结果依然有效。这1年我们经历了很多眼花缭乱的key value存储产品的诱惑，从Cassandra的淡出(Twitter暂停在主业务使用)到HBase的兴起(Facebook新的邮箱业务选用HBase(2))，当再回头再去看Redis，发现这个只有1万多行源代码的程序充满了神奇及大量未经挖掘的特性。Redis性能惊人，国内前十大网站的子产品估计用1台Redis就可以满足存储及Cache的需求。除了性能印象之外，业界其实普遍对Redis的认识存在一定误区。本文提出一些观点供大家探讨。 1. Redis是什么 这个问题的结果影响了我们怎么用Redis。如果你认为Redis是一个key value store, 那可能会用它来代替MySQL；如果认为它是一个可以持久化的cache, 可能只是它保存一些频繁访问的临时数据。Redis是REmote DIctionary Server的缩写，在Redis在官方网站的的副标题是A persistent key-value database with built-in net interface written in ANSI-C for Posix systems，这个定义偏向key value store。还有一些看法则认为Redis是一个memory database，因为它的高性能都是基于内存操作的基础。另外一些人则认为Redis是一个data structure server，因为Redis支持复杂的数据特性，比如List, Set等。对Redis的作用的不同解读决定了你对Redis的使用方式。 互联网数据目前基本使用两种方式来存储，关系数据库或者key value。但是这些互联网业务本身并不属于这两种数据类型，比如用户在社会化平台中的关系，它是一个list，如果要用关系数据库存储就需要转换成一种多行记录的形式，这种形式存在很多冗余数据，每一行需要存储一些重复信息。如果用key value存储则修改和删除比较麻烦，需要将全部数据读出再写入。Redis在内存中设计了各种数据类型，让业务能够高速原子的访问这些数据结构，并且不需要关心持久存储的问题，从架构上解决了前面两种存储需要走一些弯路的问题。 2. Redis不可能比Memcache快 很多开发者都认为Redis不可能比Memcached快，Memcached完全基于内存，而Redis具有持久化保存特性，即使是异步的，Redis也不可能比Memcached快。但是测试结果基本是Redis占绝对优势。一直在思考这个原因，目前想到的原因有这几方面。 Libevent。和Memcached不同，Redis并没有选择libevent。Libevent为了迎合通用性造成代码庞大(目前Redis代码还不到libevent的1/3)及牺牲了在特定平台的不少性能。Redis用libevent中两个文件修改实现了自己的epoll event [...]]]></description>
			<content:encoded><![CDATA[<p>转自 <a href="http://timyang.net/data/redis-misunderstanding/">http://timyang.net/data/redis-misunderstanding/</a></p>
<p>前几天微博发生了一起大的<a href="http://tech.sina.com.cn/i/2010-12-01/15324930344.shtml">系统故障</a>，很多技术的朋友都比较关心，其中的原因不会超出James Hamilton在On Designing and Deploying Internet-Scale Service(1)概括的那几个范围，James第一条经验“Design for failure”是所有互联网架构成功的一个关键。互联网系统的工程理论其实非常简单，James paper中内容几乎称不上理论，而是多条实践经验分享，每个公司对这些经验的理解及执行力决定了架构成败。</p>
<p>题外话说完，最近又研究了<a href="http://code.google.com/p/redis/">Redis</a>。去年曾做过一个<a href="http://timyang.net/data/mcdb-tt-redis/">MemcacheDB, Tokyo Tyrant, Redis performance test</a>，到目前为止，这个benchmark结果依然有效。这1年我们经历了很多眼花缭乱的key value存储产品的诱惑，从Cassandra的淡出(Twitter暂停在主业务使用)到HBase的兴起(Facebook新的邮箱业务选用HBase(2))，当再回头再去看Redis，发现这个只有1万多行源代码的程序充满了神奇及大量未经挖掘的特性。Redis性能惊人，国内前十大网站的子产品估计用1台Redis就可以满足存储及Cache的需求。除了性能印象之外，业界其实普遍对Redis的认识存在一定误区。本文提出一些观点供大家探讨。</p>
<h3>1. Redis是什么</h3>
<p>这个问题的结果影响了我们怎么用Redis。如果你认为Redis是一个key value store, 那可能会用它来代替MySQL；如果认为它是一个可以持久化的cache, 可能只是它保存一些频繁访问的临时数据。Redis是REmote DIctionary Server的缩写，在Redis在官方网站的的副标题是A persistent key-value database with built-in net interface written in ANSI-C for Posix systems，这个定义偏向key value store。还有一些看法则认为Redis是一个memory database，因为它的高性能都是基于内存操作的基础。另外一些人则认为Redis是一个data structure server，因为Redis支持复杂的数据特性，比如List, Set等。对Redis的作用的不同解读决定了你对Redis的使用方式。</p>
<p>互联网数据目前基本使用两种方式来存储，关系数据库或者key value。但是这些互联网业务本身并不属于这两种数据类型，比如用户在社会化平台中的关系，它是一个list，如果要用关系数据库存储就需要转换成一种多行记录的形式，这种形式存在很多冗余数据，每一行需要存储一些重复信息。如果用key value存储则修改和删除比较麻烦，需要将全部数据读出再写入。Redis在内存中设计了各种数据类型，让业务能够高速原子的访问这些数据结构，并且不需要关心持久存储的问题，从架构上解决了前面两种存储需要走一些弯路的问题。</p>
<h3>2. Redis不可能比Memcache快</h3>
<p>很多开发者都认为Redis不可能比Memcached快，Memcached完全基于内存，而Redis具有持久化保存特性，即使是异步的，Redis也不可能比Memcached快。但是测试结果基本是Redis占绝对优势。一直在思考这个原因，目前想到的原因有这几方面。</p>
<ul>
<li><a href="http://monkey.org/~provos/libevent/">Libevent</a>。和Memcached不同，Redis并没有选择libevent。Libevent为了迎合通用性造成代码庞大(目前Redis代码还不到libevent的1/3)及牺牲了在特定平台的不少性能。Redis用libevent中两个文件修改实现了自己的epoll event loop(4)。业界不少开发者也建议Redis使用另外一个libevent高性能替代libev，但是作者还是坚持Redis应该小巧并去依赖的思路。一个印象深刻的细节是编译Redis之前并不需要执行./configure。</li>
<li>CAS问题。CAS是Memcached中比较方便的一种防止竞争修改资源的方法。CAS实现需要为每个cache key设置一个隐藏的cas token，cas相当value版本号，每次set会token需要递增，因此带来CPU和内存的双重开销，虽然这些开销很小，但是到单机10G+ cache以及QPS上万之后这些开销就会给双方相对带来一些细微性能差别(5)。</li>
</ul>
<h3>3. 单台Redis的存放数据必须比物理内存小</h3>
<p>Redis的数据全部放在内存带来了高速的性能，但是也带来一些不合理之处。比如一个中型网站有100万注册用户，如果这些资料要用Redis来存储，内存的容量必须能够容纳这100万用户。但是业务实际情况是100万用户只有5万活跃用户，1周来访问过1次的也只有15万用户，因此全部100万用户的数据都放在内存有不合理之处，RAM需要为冷数据买单。</p>
<p>这跟操作系统非常相似，操作系统所有应用访问的数据都在内存，但是如果物理内存容纳不下新的数据，操作系统会智能将部分长期没有访问的数据交换到磁盘，为新的应用留出空间。现代操作系统给应用提供的并不是物理内存，而是虚拟内存(Virtual Memory)的概念。</p>
<p>基于相同的考虑，Redis 2.0也增加了VM特性。让Redis数据容量突破了物理内存的限制。并实现了数据冷热分离。</p>
<h3>4. Redis的VM实现是重复造轮子</h3>
<p>Redis的VM依照之前的epoll实现思路依旧是自己实现。但是在前面操作系统的介绍提到OS也可以自动帮程序实现冷热数据分离，Redis只需要OS申请一块大内存，OS会自动将热数据放入物理内存，冷数据交换到硬盘，另外一个知名的“理解了现代操作系统(3)”的Varnish就是这样实现，也取得了非常成功的效果。</p>
<p>作者antirez在解释为什么要自己实现VM中提到几个原因(6)。主要OS的VM换入换出是基于Page概念，比如OS VM1个Page是4K, 4K中只要还有一个元素即使只有1个字节被访问，这个页也不会被SWAP, 换入也同样道理，读到一个字节可能会换入4K无用的内存。而Redis自己实现则可以达到控制换入的粒度。另外访问操作系统SWAP内存区域时block进程，也是导致Redis要自己实现VM原因之一。</p>
<h3>5. 用get/set方式使用Redis</h3>
<p>作为一个key value存在，很多开发者自然的使用set/get方式来使用Redis，实际上这并不是最优化的使用方法。尤其在未启用VM情况下，Redis全部数据需要放入内存，节约内存尤其重要。</p>
<p>假如一个key-value单元需要最小占用512字节，即使只存一个字节也占了512字节。这时候就有一个设计模式，可以把key复用，几个key-value放入一个key中，value再作为一个set存入，这样同样512字节就会存放10-100倍的容量。</p>
<p>这就是为了节约内存，建议使用hashset而不是set/get的方式来使用Redis，详细方法见参考文献(7)。</p>
<h3>6. 使用aof代替snapshot</h3>
<p>Redis有两种存储方式，默认是snapshot方式，实现方法是定时将内存的快照(snapshot)持久化到硬盘，这种方法缺点是持久化之后如果出现crash则会丢失一段数据。因此在完美主义者的推动下作者增加了aof方式。aof即append only mode，在写入内存数据的同时将操作命令保存到日志文件，在一个并发更改上万的系统中，命令日志是一个非常庞大的数据，管理维护成本非常高，恢复重建时间会非常长，这样导致失去aof高可用性本意。另外更重要的是Redis是一个内存数据结构模型，所有的优势都是建立在对内存复杂数据结构高效的原子操作上，这样就看出aof是一个非常不协调的部分。</p>
<p>其实aof目的主要是数据可靠性及高可用性，在Redis中有另外一种方法来达到目的：Replication。由于Redis的高性能，复制基本没有延迟。这样达到了防止单点故障及实现了高可用。</p>
<h3>小结</h3>
<p>要想成功使用一种产品，我们需要深入了解它的特性。Redis性能突出，如果能够熟练的驾驭，对国内很多大型应用具有很大帮助。希望更多同行加入到Redis使用及代码研究行列。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gosoa.com.cn/nosql-redis%e5%87%a0%e4%b8%aa%e8%ae%a4%e8%af%86%e8%af%af%e5%8c%ba/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>推荐一款PHP调试工具 &#8212; FirePHP</title>
		<link>http://www.gosoa.com.cn/%e6%8e%a8%e8%8d%90%e4%b8%80%e6%ac%bephp%e8%b0%83%e8%af%95%e5%b7%a5%e5%85%b7-firephp</link>
		<comments>http://www.gosoa.com.cn/%e6%8e%a8%e8%8d%90%e4%b8%80%e6%ac%bephp%e8%b0%83%e8%af%95%e5%b7%a5%e5%85%b7-firephp#comments</comments>
		<pubDate>Sat, 01 Jan 2011 03:34:14 +0000</pubDate>
		<dc:creator>scofield</dc:creator>
				<category><![CDATA[PHP开发]]></category>
		<category><![CDATA[firephp]]></category>
		<category><![CDATA[PHP调试]]></category>

		<guid isPermaLink="false">http://www.gosoa.com.cn/?p=533</guid>
		<description><![CDATA[PHP调试工具之 &#8212; FirePHP PHP调试有很多中方法。今天给大家推荐的是 FirePHP（http://www.firephp.org/）。 这个工具，是基于firefox的一个组件。Firephp组件安装地址。使用之前需要先安装下这个组件。完了还需要down一个FirePHP的包。下载地址。 下载完成后可以看到包里的文件如下： 我们现在来写个例子测试下。（需要include 进来fb.php文件哦）代码如下： 我们在firefox下运行。结果如下： 在这里就可以看到$str的值了。 接下来来介绍下FirePHP的几个常用方法： 1、  fb($para) 该方法就是如上示例。可以监测某个变量的值。该方法等同于FB::log($para)。 2、  FB:: info ($str);   该方法和fb()方法类似。不同的地方在于其运行结果在firefox中会有个不同的标志。（见图三） 3、  FB::warn($str);   同上类似。 4、  FB::error($str);   同上类似。 图三 5、  FB::trace($str); 该方法用于监控变量的调用栈。如下图示例。 我们也可以在类中使用FB。如下示例： 运行结果如下： 在fb.php中，我们可以看到有如下多的方法，在这里就不一一介绍了。主要常用的就是上面五个。有兴趣的同学可以仔细去研究测试下其他方法。]]></description>
			<content:encoded><![CDATA[<p>PHP调试工具之 &#8212; FirePHP</p>
<p>PHP调试有很多中方法。今天给大家推荐的是 FirePHP（<a href="http://www.firephp.org/">http://www.firephp.org/</a>）。</p>
<p>这个工具，是基于firefox的一个组件。<a href="https://addons.mozilla.org/zh-CN/firefox/search/?q=firephp&amp;cat=all&amp;x=0&amp;y=0">Firephp组件安装地址</a>。使用之前需要先安装下这个组件。完了还需要down一个FirePHP的包。<a href="http://www.firephp.org/DownloadRelease/FirePHPLibrary-FirePHPCore-0.3.2">下载地址</a>。</p>
<p>下载完成后可以看到包里的文件如下：</p>
<p><img class="alignnone size-full wp-image-546" title="firephp" src="http://www.gosoa.com.cn/wp-content/uploads/2011/01/image001.gif" alt="" width="223" height="130" /></p>
<p>我们现在来写个例子测试下。（需要include 进来fb.php文件哦）代码如下：</p>
<p><img class="alignnone size-full wp-image-547" title="firephp - 2" src="http://www.gosoa.com.cn/wp-content/uploads/2011/01/image002.gif" alt="" width="408" height="81" /></p>
<p>我们在firefox下运行。结果如下：<br />
<img class="alignnone size-full wp-image-547" title="firephp - 3" src="http://www.gosoa.com.cn/wp-content/uploads/2011/01/image003.gif" alt="firephp - 3" /></p>
<p>在这里就可以看到$str的值了。</p>
<p>接下来来介绍下FirePHP的几个常用方法：</p>
<p>1、  <strong>fb($para) </strong>该方法就是如上示例。可以监测某个变量的值。该方法等同于FB::log($para)。</p>
<p>2、  FB:: info ($str);   该方法和fb()方法类似。不同的地方在于其运行结果在firefox中会有个不同的标志。（见图三）</p>
<p>3、  FB::warn($str);   同上类似。</p>
<p>4、  FB::error($str);   同上类似。</p>
<p><img class="alignnone size-full wp-image-549" title="firephp " src="http://www.gosoa.com.cn/wp-content/uploads/2011/01/image004.jpg" alt="" width="277" height="166" /><br />
图三</p>
<p>5、  FB::trace($str); 该方法用于监控变量的调用栈。如下图示例。<br />
<img class="alignnone size-full wp-image-550" title="firephp" src="http://www.gosoa.com.cn/wp-content/uploads/2011/01/image005.jpg" alt="" width="431" height="160" /></p>
<p>我们也可以在类中使用FB。如下示例：<br />
<img class="alignnone size-full wp-image-551" title="firephp" src="http://www.gosoa.com.cn/wp-content/uploads/2011/01/image006.jpg" alt="" width="229" height="269" /></p>
<p>运行结果如下：<br />
<img class="alignnone size-full wp-image-552" title="firephp" src="http://www.gosoa.com.cn/wp-content/uploads/2011/01/image007.jpg" alt="firephp" width="362" height="192" /></p>
<p>在fb.php中，我们可以看到有如下多的方法，在这里就不一一介绍了。主要常用的就是上面五个。有兴趣的同学可以仔细去研究测试下其他方法。</p>
<p><img class="alignnone size-full wp-image-554" title="firephp" src="http://www.gosoa.com.cn/wp-content/uploads/2011/01/image008.jpg" alt="firephp" width="360" height="310" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.gosoa.com.cn/%e6%8e%a8%e8%8d%90%e4%b8%80%e6%ac%bephp%e8%b0%83%e8%af%95%e5%b7%a5%e5%85%b7-firephp/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

