<?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/"
	>

<channel>
	<title> PHP5研究室</title>
	<atom:link href="http://www.phpv.net/rss" rel="self" type="application/rss+xml" />
	<link>http://www.phpv.net/</link>
	<description>PHP5研究室是提供PHP,mysql,linux,apache,WEB标准等精华文章的网站</description>
	<pubDate>Fri, 03 Sep 2010 08:30:06 +0800</pubDate>
	<generator>Chiron ver1.0</generator>
	<language>zh-cn</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
									<item>
					<title>淘宝的可伸缩高性能互联网架构揭密</title>
					<link>http://www.phpv.net/html/1713.html</link>
					<comments>http://www.phpv.net/html/1713.html#comment</comments>
					<pubDate>Mon, 12 Jul 2010 10:38:18 +0800</pubDate>
					<dc:creator></dc:creator>
					<category><![CDATA[PHP研究]]></category>
					<guid isPermaLink="false">http://www.phpv.net/html/1713.html</guid>
					<description><![CDATA[这是淘宝内部员工在其个人博客发布的关于淘宝架构的文章,很多信息都是第一次披露. 转过来供大家参考]]></description>
					<content:encoded><![CDATA[<p>
	<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 时间过得很快，来淘宝已经两个月了，在这两个月的时间里，自己也感受颇深。下面就结合淘宝目前的一些底层技术框架以及自己的一些感触来说说如何构建一个可 伸缩，高性能，高可用性的分布式互联网应用。</span></p>
<h1 style="margin: 12pt 0cm;">
	<span><span style="font-size: large;"><span>一</span><span style="font-family: Calibri;"> </span><span>应用无状态（淘宝</span><span lang="EN-US"><span style="font-family: Calibri;">session</span></span><span>框架）</span></span></span></h1>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
	<span><span lang="EN-US"><span><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>俗话说，一个系 统的伸缩性的好坏取决于应用的状态如何管理。为什么这么说呢？咱们试想一下，假如我们在</span><span lang="EN-US"><span style="font-family: Calibri;">session</span></span><span>中保存了大量与客户端的状态信 息的话，那么当保存状态信息的</span><span lang="EN-US"><span style="font-family: Calibri;">server</span></span><span>宕机的时候，我们怎么办？通常来说，我们都是通过集群来解决这个问题，而通常 所说的集群，不仅有负载均衡，更重要的是要有失效恢复</span><span lang="EN-US"><span style="font-family: Calibri;">failover,</span></span><span>比如</span><span lang="EN-US"><span style="font-family: Calibri;">tomcat</span></span><span>采 用的集群节点广播复制，</span><span lang="EN-US"><span style="font-family: Calibri;">jboss</span></span><span>采 用的配对复制等</span><span lang="EN-US"><span style="font-family: Calibri;">session</span></span><span>状 态复制策略，但是集群中的状态恢复也有其缺点，那就是严重影响了系统的伸缩性，系统不能通过增加更多的机器来达到良好的水平伸缩，因为集群节点间</span><span lang="EN-US"><span style="font-family: Calibri;">session</span></span><span>的 通信会随着节点的增多而开销增大，因此要想做到应用本身的伸缩性，我们需要保证应用的无状态性，这样集群中的各个节点来说都是相同的，从而是的系统更好的 水平伸缩。</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
	<span><span lang="EN-US"><span style="font-family: Calibri;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;</span>OK</span></span><span>， 上面说了无状态的重要性，那么具体如何实现无状态呢？此时一个</span><span lang="EN-US"><span style="font-family: Calibri;">session</span></span><span>框架就会发挥作用了。幸运的是淘 宝已经具有了此类框架。淘宝的</span><span lang="EN-US"><span style="font-family: Calibri;">session</span></span><span>框架采用的是</span><span lang="EN-US"><span style="font-family: Calibri;">client cookie</span></span><span>实现，主要将状态 保存到了</span><span lang="EN-US"><span style="font-family: Calibri;">cookie</span></span><span>里 面，这样就使得应用节点本身不需要保存任何状态信息，这样在系统用户变多的时候，就可以通过增加更多的应用节点来达到水平扩展的目的</span><span lang="EN-US"><span style="font-family: Calibri;">.</span></span><span>但 是采用客户端</span><span lang="EN-US"><span style="font-family: Calibri;">cookie</span></span><span>的 方式来保存状态也会遇到限制，比如每个</span><span lang="EN-US"><span style="font-family: Calibri;">cookie</span></span><span>一般不能超过</span><span lang="EN-US"><span style="font-family: Calibri;">4K</span></span><span>的大小，同时很多浏览器都限制一个站点最 多保存</span><span lang="EN-US"><span style="font-family: Calibri;">20</span></span><span>个</span><span lang="EN-US"><span style="font-family: Calibri;">cookie.</span></span><span>淘 宝</span><span lang="EN-US"><span style="font-family: Calibri;">cookie</span></span><span>框 架采用的是&ldquo;多值</span><span lang="EN-US"><span style="font-family: Calibri;">cookie</span></span><span>&rdquo;， 就是一个组合键对应多个</span><span lang="EN-US"><span style="font-family: Calibri;">cookie</span></span><span>的 值，这样不仅可以防止</span><span lang="EN-US"><span style="font-family: Calibri;">cookie</span></span><span>数 量超过</span><span lang="EN-US"><span style="font-family: Calibri;">20</span></span><span>， 同时还节省了</span><span lang="EN-US"><span style="font-family: Calibri;">cookie</span></span><span>存 储有效信息的空间，因为默认每个</span><span lang="EN-US"><span style="font-family: Calibri;">cookie</span></span><span>都会有大约</span><span lang="EN-US"><span style="font-family: Calibri;">50</span></span><span>个字节的元信息来描述</span><span lang="EN-US"><span style="font-family: Calibri;">cookie</span></span><span>。</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
	<span><span lang="EN-US"><span style="font-family: Calibri;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;</span></span></span><span>除 了淘宝目前的</span><span lang="EN-US"><span style="font-family: Calibri;">session</span></span><span>框 架的实现方式以外，其实集中式</span><span lang="EN-US"><span style="font-family: Calibri;">session</span></span><span>管理来完成，说具体点就是多个无状态的应用节点连接一个</span><span lang="EN-US"><span style="font-family: Calibri;">session </span></span><span>服 务器，</span><span lang="EN-US"><span style="font-family: Calibri;">session</span></span><span>服 务器将</span><span lang="EN-US"><span style="font-family: Calibri;">session</span></span><span>保 存到缓存中，</span><span lang="EN-US"><span style="font-family: Calibri;">session</span></span><span>服 务器后端再配有底层持久性数据源，比如数据库，文件系统等等。</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
	<span>&nbsp;</span></p>
<p>
	<span>&nbsp;</span></p>
<p>
	&nbsp;</p>
<h1 style="margin: 12pt 0cm;">
	<span><span><span style="font-size: large;"><span>二</span><span style="font-family: Calibri;"> </span><span>有效使用缓存（</span><span lang="EN-US"><span style="font-family: Calibri;">Tair</span></span><span>）</span></span></span></span></h1>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
	<span><span><span lang="EN-US"><span style="font-family: Calibri;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;</span></span></span><span>做 互联网应用的兄弟应该都清楚，缓存对于一个互联网应用是多么的重要，从浏览器缓存，反向代理缓存，页面缓存，局部页面缓存，对象缓存等等都是缓存应用的场 景。</span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
	<span><span><span lang="EN-US"><span style="font-family: Calibri;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;</span></span></span><span>一 般来说缓存根据与应用程序的远近程度不同可以分为：</span><span lang="EN-US"><span style="font-family: Calibri;">local cache </span></span><span>和</span><span lang="EN-US"><span style="font-family: Calibri;"> remote cache</span></span><span>。 一般系统中要么采用</span><span lang="EN-US"><span style="font-family: Calibri;">local cache</span></span><span>，要么采用</span><span lang="EN-US"><span style="font-family: Calibri;">remote cache,</span></span><span>两者混合使用的话对 于</span><span lang="EN-US"><span style="font-family: Calibri;">local cache</span></span><span>和</span><span lang="EN-US"><span style="font-family: Calibri;">remote cache</span></span><span>的数据一致性处理会变 大比较麻烦</span><span lang="EN-US"><span style="font-family: Calibri;">.</span></span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
	<span><span><span lang="EN-US"><span style="font-family: Calibri;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;</span></span></span><span>在 大部分情况下</span><span lang="EN-US"><span style="font-family: Calibri;">,</span></span><span>我 们所说到的缓存都是读缓存</span><span lang="EN-US"><span style="font-family: Calibri;">,</span></span><span>缓存还有另外一个类型</span><span lang="EN-US"><span style="font-family: Calibri;">:</span></span><span>写缓存</span><span lang="EN-US"><span style="font-family: Calibri;">.<span>&nbsp; </span></span></span><span>对 于一些读写比不高，同时对数据安全性需求不高的数据，我们可以将其缓存起来从而减少对底层数据库的访问</span><span lang="EN-US"><span style="font-family: Calibri;">,</span></span><span>比如 统计商品的访问次数</span><span lang="EN-US"><span style="font-family: Calibri;">,</span></span><span>统 计</span><span lang="EN-US"><span style="font-family: Calibri;">API</span></span><span>的 调用量等等</span><span lang="EN-US"><span style="font-family: Calibri;">,</span></span><span>可 以采用先写内存缓存然后延迟持久化到数据库，这样可以大大减少对数据库的写压力。</span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
	<span><span><span lang="EN-US"><span style="font-family: Calibri;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;</span>OK</span></span><span>， 我以店铺线的系统为例，在用户浏览店铺的时候，比如店铺介绍，店铺交流区页面，店铺服务条款页面，店铺试衣间页面，以及店铺内搜索界面这些界面更新不是非 常频繁，因此适合放到缓存中，这样可以大大减低</span><span lang="EN-US"><span style="font-family: Calibri;">DB</span></span><span>的负载。另外宝贝详情页面相对也更新比较 少，因此也适合放到缓存中来减低</span><span lang="EN-US"><span style="font-family: Calibri;">DB</span></span><span>负载。</span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
	<span><span>&nbsp;</span></span></p>
<p>
	<span><span>&nbsp;</span></span></p>
<p>
	&nbsp;</p>
<h1 style="margin: 12pt 0cm;">
	<span><span><span><span style="font-size: large;"><span>三</span><span style="font-family: Calibri;"> </span><span>应用拆分（</span><span lang="EN-US"><span style="font-family: Calibri;">HSF</span></span><span>）</span></span></span></span></span></h1>
<p class="MsoNormal" style="text-indent: 21pt; margin: 0cm 0cm 0pt;">
	<span><span><span><span>首 先，在说明应用拆分之前，我们先来回顾一下一个系统从小变大的过程中遇到的一些问题，通过这些问题我们会发现拆分对于构建一个大型系统是如何的重要。</span></span></span></span></p>
<p class="MsoNormal" style="text-indent: 21pt; margin: 0cm 0cm 0pt;">
	<span><span><span><span>系 统刚上线初期，用户数并不多，所有的逻辑也许都是放在一个系统中的，所有逻辑跑到一个进程或者一个应用当中，这个时候因为比较用户少，系统访问量低，因此 将全部的逻辑都放在一个应用未尝不可。但是，兄弟们都清楚，好景不长，随着系统用户的不断增加，系统的访问压力越来越多，同时随着系统发展，为了满足用户 的需求，原有的系统需要增加新的功能进来，系统变得越来越复杂的时候，我们会发现系统变得越来越难维护，难扩展，同时系统伸缩性和可用性也会受到影响。那 么这个时候我们如何解决这些问题呢？明智的办法就是拆分（这也算是一种解耦），我们需要将原来的系统根据一定的标准，比如业务相关性等分为不同的子系统， 不同的系统负责不同的功能，这样切分以后，我们可以对单独的子系统进行扩展和维护，从而提高系统的扩展性和可维护性，同时我们系统的水平伸缩性</span><span lang="EN-US"><span style="font-family: Calibri;">scale out</span></span><span>大 大的提升了，因为我们可以有针对性的对压力大的子系统进行水平扩展而不会影响到其它的子系统，而不会像拆分以前，每次系统压力变大的时候，我们都需要对整 个大系统进行伸缩，而这样的成本是比较大的，另外经过切分，子系统与子系统之间的耦合减低了，当某个子系统暂时不可用的时候，整体系统还是可用的，从而整 体系统的可用性也大大增强了。</span><span style="font-family: Calibri;"> </span></span></span></span></p>
<p class="MsoNormal" style="text-indent: 24pt; margin: 0cm 0cm 0pt;">
	<span><span><span><span>因 此一个大型的互联网应用，肯定是要经过拆分，因为只有拆分了，系统的扩展性，维护性</span><span lang="EN-US"><span style="font-family: Calibri;">,</span></span><span>伸缩性，可用性才会变的更好。但是拆分也给系 统带来了问题，就是子系统之间如何通信的问题，而具体的通信方式有哪些呢？一般有同步通信和异步通信，这里我们首先来说下同步通信，下面的主题&ldquo;消息系 统&rdquo;会说到异步通信。既然需要通信，这个时候一个高性能的远程调用框架就显得非常总要啦，因此咱们淘宝也有了自己的</span><span lang="EN-US"><span style="font-family: Calibri;">HSF</span></span><span>框 架。</span></span></span></span></p>
<p class="MsoNormal" style="text-indent: 24pt; margin: 0cm 0cm 0pt;">
	<span><span><span>&nbsp;</span></span></span></p>
<p class="MsoNormal" style="text-indent: 24pt; margin: 0cm 0cm 0pt;">
	<span><span><span><span>上 面所说的都是拆分的好处，但是拆分以后必然的也会带来新的问题，除了刚才说的子系统通信问题外，最值得关注的问题就是系统之间的依赖关系，因为系统多了， 系统的依赖关系就会变得复杂，此时就需要更好的去关注拆分标准，比如能否将一些有依赖的系统进行垂直化，使得这些系统的功能尽量的垂直，这也是目前淘宝正 在做的系统垂直化，同时一定要注意系统之间的循环依赖，如果出现循环依赖一定要小心，因为这可能导致系统连锁启动失败。</span></span></span></span></p>
<p class="MsoNormal" style="text-indent: 24pt; margin: 0cm 0cm 0pt;">
	<span><span><span><span lang="EN-US"><span style="font-family: Calibri;">OK</span></span><span>， 既然明白了拆分的重要性，我们看看随着淘宝的发展，淘宝本身是如何拆分系统的。</span></span></span></span></p>
<p class="MsoNormal" style="text-indent: 24pt; margin: 0cm 0cm 0pt;">
	<span><span><span><span>首 先我们来看以下这个图：</span></span></span></span></p>
<p>
	<span><span><span>&nbsp;</span></span></span></p>
<p class="MsoNormal" style="text-indent: 24pt; margin: 0cm 0cm 0pt;">
	<span><span><span><span><img alt="" height="341" src="http://dl.javaeye.com/upload/attachment/276266/6a282f12-3130-3404-88ad-027f4d12a4da.jpg" width="552" /></span></span></span></span></p>
<p>
	<span><span><span>&nbsp;</span></span></span></p>
<p class="MsoNormal" style="text-indent: 24pt; margin: 0cm 0cm 0pt;">
	<span><span><span>&nbsp;</span></span></span></p>
<p class="MsoNormal" style="text-indent: 24pt; margin: 0cm 0cm 0pt;">
	<span><span><span>&nbsp;</span></span></span></p>
<p>
	<span><span><span>&nbsp;</span></span></span></p>
<p>
	&nbsp;</p>
<p class="MsoNormal" style="text-indent: 24pt; margin: 0cm 0cm 0pt;">
	<span><span><span><span><span>从 上面的图可以看出淘宝系统的一个演变过程，在这个演变的过程中，我们所说的拆分就出现</span><span lang="EN-US"><span style="font-family: Calibri;">V2.2</span></span><span>和</span><span lang="EN-US"><span style="font-family: Calibri;">V3.0</span></span><span>之 间。在</span><span lang="EN-US"><span style="font-family: Calibri;">V2.2</span></span><span>版 本中，淘宝几乎所有的逻辑都放在</span><span lang="EN-US"><span style="font-family: Calibri;">(Denali)</span></span><span>系统中，这样导致的问题就是系统扩展和修改非常麻烦，并且更加致命的是随 着淘宝业务量的增加，如果按照</span><span lang="EN-US"><span style="font-family: Calibri;">V2.2</span></span><span>的架构已经没有办法支撑以后淘宝的快速发展，因此大家决定对整个系统进行拆分，最 终</span><span lang="EN-US"><span style="font-family: Calibri;">V3.0</span></span><span>版 本的淘宝系统架构图如下：</span></span></span></span></span></p>
<p>
	<span><span><span><span>&nbsp;</span></span></span></span></p>
<p class="MsoNormal" style="text-indent: 24pt; margin: 0cm 0cm 0pt;">
	<span><span><span><span><span><img alt="" height="355" src="http://dl.javaeye.com/upload/attachment/276268/921ffa6d-3a1f-3297-ba46-ed19d6cff6bb.jpg" width="469" /></span></span></span></span></span></p>
<p>
	<span><span><span><span>&nbsp;</span></span></span></span></p>
<p class="MsoNormal" style="text-indent: 24pt; margin: 0cm 0cm 0pt;">
	<span><span><span><span>&nbsp;</span></span></span></span></p>
<p>
	<span><span><span><span>&nbsp;</span></span></span></span></p>
<p>
	&nbsp;</p>
<p class="MsoNormal" style="text-indent: 24pt; margin: 0cm 0cm 0pt;">
	<span><span><span><span><span><span>从 上图可以看出</span><span lang="EN-US"><span style="font-family: Calibri;">V3.0</span></span><span>版 本的系统对整个系统进行了水平和垂直两个方向的拆分，水平方向上，按照功能分为交易，评价，用户，商品等系统，同样垂直方向上，划分为业务系统，核心业务 系统以及以及基础服务，这样以来，各个系统都可以独立维护和独立的进行水平伸缩，比如交易系统可以在不影响其它系统的情况下独立的进行水平伸缩以及功能扩 展。</span></span></span></span></span></span></p>
<p class="MsoNormal" style="text-indent: 24pt; margin: 0cm 0cm 0pt;">
	<span><span><span><span><span>&nbsp;</span></span></span></span></span></p>
<p>
	<span><span><span><span><span>&nbsp;</span></span></span></span></span></p>
<p>
	&nbsp;</p>
<p class="MsoNormal" style="text-indent: 24pt; margin: 0cm 0cm 0pt;">
	<span><span><span><span><span><span><span><span style="font-family: Calibri;">&nbsp;</span></span><span>从上面可以看出，一个大型系统要想变得可维 护，可扩展，可伸缩，我们必须的对它进行拆分，拆分必然也带来系统之间如何通信以及系统之间依赖管理等问题，关于通信方面，淘宝目前独立开发了自己的高性 能服务框架</span><span lang="EN-US"><span style="font-family: Calibri;">HSF</span></span><span>， 此框架主要解决了淘宝目前所有子系统之间的同步和异步通信（目前</span><span lang="EN-US"><span style="font-family: Calibri;">HSF</span></span><span>主要用于同步场合，</span><span lang="EN-US"><span style="font-family: Calibri;">FutureTask</span></span><span>方 式的调用场景还比较少）。至于系统间的依赖管理，目前淘宝还做的不够好，这应该也是我们以后努力解决的问题。</span></span></span></span></span></span></span></p>
<p>
	<span><span><span><span><span><span>&nbsp;</span></span></span></span></span></span></p>
<p>
	&nbsp;</p>
<h1 style="margin: 12pt 0cm;">
	<span><span><span><span><span><span><span><span style="font-size: large;"><span>四</span><span style="font-family: Calibri;"> </span><span>数据库拆分（</span><span lang="EN-US"><span style="font-family: Calibri;">TDDL</span></span><span>）</span></span></span></span></span></span></span></span></span></h1>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
	<span><span><span><span><span><span><span><span lang="EN-US"><span style="font-family: Calibri;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;</span></span></span><span>在 前面&ldquo;应用拆分&rdquo;主题中，我们提到了一个大型互联网应用需要进行良好的拆分，而那里我们仅仅说了</span><span lang="EN-US"><span style="font-family: Calibri;">&rdquo;</span></span><span>应用级别</span><span lang="EN-US"><span style="font-family: Calibri;">&rdquo;</span></span><span>的拆 分，其实我们的互联网应用除了应用级别的拆分以外，还有另外一个很重要的层面就是存储如何拆分的。因此这个主题主要涉及到如何对存储系统，通常就是所说的</span><span lang="EN-US"><span style="font-family: Calibri;">RDBMS</span></span><span>进 行拆分。</span></span></span></span></span></span></span></span></p>
<p class="MsoNormal" style="text-indent: 27pt; margin: 0cm 0cm 0pt;">
	<span><span><span><span><span><span><span><span>好 了，确定了这个小节的主题之后，我们回顾一下，一个互联网应用从小变大的过程中遇到的一些问题，通过遇到的问题来引出我们拆分</span><span lang="EN-US"><span style="font-family: Calibri;">RDBMS</span></span><span>的 重要性。</span></span></span></span></span></span></span></span></p>
<p class="MsoNormal" style="text-indent: 27pt; margin: 0cm 0cm 0pt;">
	<span><span><span><span><span><span><span><span>系 统刚开始的时候，因为系统刚上线，用户不多，那个时候，所有的数据都放在了同一个数据库中，这个时候因为用户少压力小，一个数据库完全可以应付的了，但是 随着运营那些哥们辛苦的呐喊和拼命的推广以后，突然有一天发现，</span><span lang="EN-US"><span style="font-family: Calibri;">oh,god,</span></span><span>用户数量突然变多了起来，随之而 来的就是数据库这哥们受不了，它终于在某一天大家都和惬意的时候挂掉啦。此时，咱们搞技术的哥们，就去看看究竟是啥原因，我们查了查以后，发现原来是数据 库读取压力太大了，此时咱们都清楚是到了读写分离的时候，这个时候我们会配置一个</span><span lang="EN-US"><span style="font-family: Calibri;">server</span></span><span>为</span><span lang="EN-US"><span style="font-family: Calibri;">master</span></span><span>节 点，然后配几个</span><span lang="EN-US"><span style="font-family: Calibri;">salve</span></span><span>节 点，这样以来通过读写分离，使得读取数据的压力分摊到了不同的</span><span lang="EN-US"><span style="font-family: Calibri;">salve</span></span><span>节点上面，系统终于又恢复了正常，开 始正常运行了。但是好景还是不长，有一天我们发现</span><span lang="EN-US"><span style="font-family: Calibri;">master</span></span><span>这哥们撑不住了，它负载老高了，汗 流浃背，随时都有翘掉的风险，这个时候就需要咱们垂直分区啦（也就是所谓的分库），比如将商品信息，用户信息，交易信息分别存储到不同的数据库中，同时还 可以针对商品信息的库采用</span><span lang="EN-US"><span style="font-family: Calibri;">master</span></span><span>，</span><span lang="EN-US"><span style="font-family: Calibri;">salve</span></span><span>模式，</span><span lang="EN-US"><span style="font-family: Calibri;">OK</span></span><span>， 通过分库以后，各个按照功能拆分的数据库写压力被分担到了不同的</span><span lang="EN-US"><span style="font-family: Calibri;">server</span></span><span>上面，这样数据库的压力终于有恢复 到正常状态。但是是不是这样，我们就可以高枕无忧了呢？</span><span lang="EN-US"><span style="font-family: Calibri;">NO,</span></span><span>这个</span><span lang="EN-US"><span style="font-family: Calibri;">NO</span></span><span>， 不是我说的，是前辈们通过经验总结出来的，随着用户量的不断增加，你会发现系统中的某些表会变的异常庞大，比如好友关系表，店铺的参数配置表等，这个时候 无论是写入还是读取这些表的数据，对数据库来说都是一个很耗费精力的事情，因此此时就需要我们进行&ldquo;水平分区&rdquo;了（这就是俗话说的分表，或者说</span><span lang="EN-US"><span style="font-family: Calibri;">sharding</span></span><span>）</span><span lang="EN-US"><span style="font-family: Calibri;">.</span></span></span></span></span></span></span></span></span></p>
<p class="MsoNormal" style="text-indent: 27pt; margin: 0cm 0cm 0pt;">
	<span><span><span><span><span><span><span><span lang="EN-US"><span style="font-family: Calibri;">OK,</span></span><span>上 面说了一大堆，无非就是告诉大家一个事实&ldquo;数据库是系统中最不容易</span><span lang="EN-US"><span style="font-family: Calibri;">scale out</span></span><span>的一层&rdquo;，一个大型的互联网 应用必然会经过一个从单一</span><span lang="EN-US"><span style="font-family: Calibri;">DB server,</span></span><span>到</span><span lang="EN-US"><span style="font-family: Calibri;">Master/salve,</span></span><span>再到垂直分区（分 库），然后再到水平分区（分表，</span><span lang="EN-US"><span style="font-family: Calibri;">sharding</span></span><span>）的过程，而在这个过程中，</span><span lang="EN-US"><span style="font-family: Calibri;">Master/salve </span></span><span>以 及垂直分区相对比较容易，对应用的影响也不是很大，但是分表会引起一些棘手的问题，比如不能跨越多个分区</span><span lang="EN-US"><span style="font-family: Calibri;">join</span></span><span>查 询数据，如何平衡各个</span><span lang="EN-US"><span style="font-family: Calibri;">shards</span></span><span>的 负载等等，这个时候就需要一个通用的</span><span lang="EN-US"><span style="font-family: Calibri;">DAL</span></span><span>框架来屏蔽底层数据存储对应用逻辑的影响，使得底层数据的访问对应用透明化。</span></span></span></span></span></span></span></span></p>
<p class="MsoNormal" style="text-indent: 27pt; margin: 0cm 0cm 0pt;">
	<span><span><span><span><span><span><span><span>拿 淘宝目前的情况来说，淘宝目前也正在从昂贵的高端存储（小型机</span><span lang="EN-US"><span style="font-family: Calibri;">+ORACLE</span></span><span>）切换到</span><span lang="EN-US"><span style="font-family: Calibri;">MYSQL,</span></span><span>切 换到</span><span lang="EN-US"><span style="font-family: Calibri;">MYSQL</span></span><span>以 后，势必会遇到垂直分区（分库）以及水平分区（</span><span lang="EN-US"><span style="font-family: Calibri;">Sharding</span></span><span>）的问题，因此目前淘宝根据自 己的业务特点也开发了自己的</span><span lang="EN-US"><span style="font-family: Calibri;">TDDL</span></span><span>框架，此框架主要解决了分库分表对应用的透明化以及异构数据库之间的数据复制。</span></span></span></span></span></span></span></span></p>
<p class="MsoNormal" style="text-indent: 27pt; margin: 0cm 0cm 0pt;">
	<span><span><span><span><span><span><span>&nbsp;</span></span></span></span></span></span></span></p>
<p>
	<span><span><span><span><span><span><span>&nbsp;</span></span></span></span></span></span></span></p>
<p>
	&nbsp;</p>
<h1 style="margin: 12pt 0cm;">
	<span><span><span><span><span><span><span><span><span style="font-size: large;"><span>五</span><span style="font-family: Calibri;"> </span><span>异步通信（</span><span lang="EN-US"><span style="font-family: Calibri;">Notify</span></span><span>）</span></span></span></span></span></span></span></span></span></span></h1>
<p class="MsoNormal" style="text-indent: 21pt; margin: 0cm 0cm 0pt;">
	<span><span><span><span><span><span><span><span><span>在</span><span lang="EN-US"><span style="font-family: Calibri;">&rdquo;</span></span><span>远 程调用框架</span><span lang="EN-US"><span style="font-family: Calibri;">&rdquo;</span></span><span>的 介绍中</span><span lang="EN-US"><span style="font-family: Calibri;">,</span></span><span>我 们说了一个大型的系统为了扩展性和伸缩性方面的需求</span><span lang="EN-US"><span style="font-family: Calibri;">,</span></span><span>肯定是要进行拆分</span><span lang="EN-US"><span style="font-family: Calibri;">,</span></span><span>但是 拆分了以后</span><span lang="EN-US"><span style="font-family: Calibri;">,</span></span><span>子 系统之间如何通信就成了我们首要的问题</span><span lang="EN-US"><span style="font-family: Calibri;">,</span></span><span>在</span><span lang="EN-US"><span style="font-family: Calibri;">&rdquo;</span></span><span>远程调用框架</span><span lang="EN-US"><span style="font-family: Calibri;">&rdquo;</span></span><span>小节 中</span><span lang="EN-US"><span style="font-family: Calibri;">,</span></span><span>我 们说了同步通信在一个大型分布式系统中的应用</span><span lang="EN-US"><span style="font-family: Calibri;">,</span></span><span>那么这一小节我们就来说说异步通信</span><span lang="EN-US"><span style="font-family: Calibri;">.</span></span><span>好了</span><span lang="EN-US"><span style="font-family: Calibri;">,</span></span><span>既 然说到了异步通信</span><span lang="EN-US"><span style="font-family: Calibri;">,</span></span><span>那 么</span><span lang="EN-US"><span style="font-family: Calibri;">&rdquo;</span></span><span>消 息中间件</span><span lang="EN-US"><span style="font-family: Calibri;">&rdquo;</span></span><span>就 要登场了</span><span lang="EN-US"><span style="font-family: Calibri;">,</span></span><span>采 用异步通信这其实也是关系到系统的伸缩性</span><span lang="EN-US"><span style="font-family: Calibri;">,</span></span><span>以及最大化的对各个子系统进行解耦</span><span lang="EN-US"><span style="font-family: Calibri;">.</span></span></span></span></span></span></span></span></span></span></p>
<p class="MsoNormal" style="text-indent: 21pt; margin: 0cm 0cm 0pt;">
	<span><span><span><span><span><span><span><span><span>说 到异步通信，我们需要关注的一点是这里的异步一定是根据业务特点来的，一定是针对业务的异步，通常适合异步的场合是一些松耦合的通信场合，而对于本身业务 上关联度比较大的业务系统之间，我们还是要采用同步通信比较靠谱。</span></span></span></span></span></span></span></span></span></p>
<p class="MsoNormal" style="text-indent: 21pt; margin: 0cm 0cm 0pt;">
	<span><span><span><span><span><span><span><span><span lang="EN-US"><span style="font-family: Calibri;">OK,</span></span><span>那 么下一步我们说说异步能给系统带来什么样子的好处。首先我们想想，假如系统有</span><span lang="EN-US"><span style="font-family: Calibri;">A</span></span><span>和</span><span lang="EN-US"><span style="font-family: Calibri;">B</span></span><span>两个 子系统构成，假如</span><span lang="EN-US"><span style="font-family: Calibri;">A</span></span><span>和</span><span lang="EN-US"><span style="font-family: Calibri;">B</span></span><span>是 同步通信的话，那么要想使得系统整体伸缩性提高必须同时对</span><span lang="EN-US"><span style="font-family: Calibri;">A</span></span><span>和</span><span lang="EN-US"><span style="font-family: Calibri;">B</span></span><span>进行 伸缩，这就影响了对整个系统进行</span><span lang="EN-US"><span style="font-family: Calibri;">scale out.</span></span><span>其次，同步调用还会影响到可用性，从数学推理的角度来说，</span><span lang="EN-US"><span style="font-family: Calibri;">A</span></span><span>同 步调用</span><span lang="EN-US"><span style="font-family: Calibri;">B</span></span><span>， 如果</span><span lang="EN-US"><span style="font-family: Calibri;">A</span></span><span>可 用，那么</span><span lang="EN-US"><span style="font-family: Calibri;">B</span></span><span>可 用，逆否命题就是如果</span><span lang="EN-US"><span style="font-family: Calibri;">B</span></span><span>不 可用，那么</span><span lang="EN-US"><span style="font-family: Calibri;">A</span></span><span>也 不可用，这将大大影响到系统可用性，再次，系统之间异步通信以后可以大大提高系统的响应时间，使得每个请求的响应时间变短，从而提高用户体验，因此异步在 提高了系统的伸缩性以及可用性的同时，也大大的增强了请求的响应时间（当然了，请求的总体处理时间也许不会变少）。</span></span></span></span></span></span></span></span></span></p>
<p>
	<span><span><span><span><span><span><span><span>&nbsp;</span></span></span></span></span></span></span></span></p>
<p class="MsoNormal" style="text-indent: 21pt; margin: 0cm 0cm 0pt;">
	<span><span><span><span><span><span><span><span><span><span>下 面我们就以淘宝的业务来看看异步在淘宝的具体应用。交易</span></span><span><span><span>系统会与很多其它的业务系统交 互，如果在一次交易过程中采用同步调用的话，这就要求要向交易成功，必须依赖的所有系统都可用，而如果采用异步通信以后，交易</span><span>系 统借助于消息中间件</span><span lang="EN-US"><span style="font-family: Calibri;">Notify</span></span><span>和 其它的系统进行了解耦，这样以来当其它的系统不可用的时候，也不会影响到某此交易，从而提高了系统的可用性。</span><span style="font-family: Calibri;"> </span> </span></span></span></span></span></span></span></span></span></span></p>
<p>
	<span><span><span><span><span><span><span><span><span><span>&nbsp;</span></span></span></span></span></span></span></span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
	<span><span><span><span><span><span><span><span><span><span><span>最后，关于异步方面的讨论，我可以 推荐大家一些资源：</span></span></span></span></span></span></span></span></span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
	<span><span><span><span><span><span><span><span><span><span><span lang="EN-US"><span style="font-family: Calibri;"><span>&nbsp;</span>1 . </span><a href="http://www.ibm.com/developerworks/web/library/wa-aj-web2jee/?S_CMP=cn-a-wa&amp;S_TACT=105AGX52"><span style="font-family: Calibri; color: rgb(0, 0, 255);">J2EE meets web2.0</span></a></span></span></span></span></span></span></span></span></span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
	<span><span><span><span><span><span><span><span><span><span><span lang="EN-US"><span style="font-family: Calibri;"><span>&nbsp;</span>2. </span><a href="http://www.jdon.com/jivejdon/thread/37753"><span style="font-family: Calibri;">Ebay</span><span><span lang="EN-US">架构特点</span></span><span style="font-family: Calibri;">(HPTS 2009)</span></a></span></span></span></span></span></span></span></span></span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
	<span><span><span><span><span><span><span><span><span><span>&nbsp;</span></span></span></span></span></span></span></span></span></span></p>
<p>
	<span><span><span><span><span><span><span><span><span><span>&nbsp;</span></span></span></span></span></span></span></span></span></span></p>
<p>
	<span><span><span><span><span><span><span><span><span><span>&nbsp;</span></span></span></span></span></span></span></span></span></span></p>
<h1 style="margin: 12pt 0cm;">
	<span><span><span><span><span><span><span><span><span><span><span style="font-size: large;"><span>六</span><span style="font-family: Calibri;"> </span><span>非结构化数据存储</span><span lang="EN-US"><span style="font-family: Calibri;"> ( TFS,NOSQL)</span></span></span></span></span></span></span></span></span></span></span></span></span></h1>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
	<span><span><span><span><span><span><span><span><span><span><span lang="EN-US"><span style="font-family: Calibri;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;</span></span></span><span>在 一个大型的互联网应用当中，我们会发现并不是所有的数据都是结构化的，比如一些配置文件，一个用户对应的动态，以及一次交易的快照等信息，这些信息一般不 适合保存到</span><span lang="EN-US"><span style="font-family: Calibri;">RDBMS</span></span><span>中， 它们更符合一种</span><span lang="EN-US"><span style="font-family: Calibri;">Key-value</span></span><span>的 结构，另外还有一类数据，数据量非常的大，但是实时性要求不高，此时这些数据也需要通过另外的一种存储方式进行存储，另外一些静态文件，比如各个商品的图 片，商品描述等信息，这些信息因为比较大，放入</span><span lang="EN-US"><span style="font-family: Calibri;">RDBMS</span></span><span>会引起读取性能问题，从而影响到其它 的数据读取性能，因此这些信息也需要和其它信息分开存储，而一般的互联网应用系统都会选择把这些信息保存到分布式文件系统中，因此淘宝目前也开发了自己的 分布式文件系统</span><span lang="EN-US"><span style="font-family: Calibri;">TFS</span></span><span>，</span><span lang="EN-US"><span style="font-family: Calibri;">TFS</span></span><span>目 前限制了文件大小为</span><span lang="EN-US"><span style="font-family: Calibri;">2M</span></span><span>， 适合于一些小于</span><span lang="EN-US"><span style="font-family: Calibri;">2M</span></span><span>数 据的存放。</span></span></span></span></span></span></span></span></span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
	<span><span><span><span><span><span><span><span><span><span><span lang="EN-US"><span style="font-family: Calibri;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;</span></span></span><span>随 着互联网的发展，业界从</span><span lang="EN-US"><span style="font-family: Calibri;">08</span></span><span>年 下半年开始逐渐流行了一个概念就是</span><span lang="EN-US"><span style="font-family: Calibri;">NOSQL</span></span><span>。我们都知道根据</span><span lang="EN-US"><span style="font-family: Calibri;">CAP</span></span><span>理论，一致性，可用性和分区容错性</span><span lang="EN-US"><span style="font-family: Calibri;">3</span></span><span>者 不能同时满足，最多只能同时满足两个，我们传统的关系数据采用了</span><span lang="EN-US"><span style="font-family: Calibri;">ACID</span></span><span>的事务策略，而</span><span lang="EN-US"><span style="font-family: Calibri;">ACID</span></span><span>的 事务策略更加讲究的是一种高一致性而降低了可用性的需求，但是互联网应用往往对可用性的要求要略高于一致性的需求，这个时候我们就需要避免采用数据的</span><span lang="EN-US"><span style="font-family: Calibri;">ACID</span></span><span>事 务策略，转而采用</span><span lang="EN-US"><span style="font-family: Calibri;">BASE</span></span><span>事 务策略，</span><span lang="EN-US"><span style="font-family: Calibri;">BASE</span></span><span>事 务策略是基本可用性，事务软状态以及最终一致性的缩写，通过</span><span lang="EN-US"><span style="font-family: Calibri;">BASE</span></span><span>事务策略，我们可以通过最终一致性来提 升系统的可用性，这也是目前很多</span><span lang="EN-US"><span style="font-family: Calibri;">NOSQL</span></span><span>产品所采用的策略，包括</span><span lang="EN-US"><span style="font-family: Calibri;">facebook </span></span><span>的</span><span lang="EN-US"><span style="font-family: Calibri;">cassandra,apache hbase,google bigtable</span></span><span>等，这些产品非常适合一些非结构化的数据，比如</span><span lang="EN-US"><span style="font-family: Calibri;">key-value</span></span><span>形 式的数据存储，并且这些产品有个很好的优点就是水平伸缩性。目前淘宝也在研究和使用一些成熟的</span><span lang="EN-US"><span style="font-family: Calibri;">NOSQL</span></span><span>产品。</span></span></span></span></span></span></span></span></span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
	<span><span><span><span><span><span><span><span><span><span><span lang="EN-US"><span><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span></span></span></span></span></span></span></span></span></span></span></p>
<h1 style="margin: 12pt 0cm;">
	<span><span><span><span><span><span><span><span><span><span><span style="font-size: large;"><span>七</span><span style="font-family: Calibri;"> </span><span>监控、预警系统</span></span></span></span></span></span></span></span></span></span></span></span></h1>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
	<span><span><span><span><span><span><span><span><span><span><span lang="EN-US"><span><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>对于大型的系统 来说，唯一可靠的就是系统的各个部分是不可靠。</span></span></span></span></span></span></span></span></span></span></span></p>
<p class="MsoNormal" style="text-indent: 18pt; margin: 0cm 0cm 0pt;">
	<span><span><span><span><span><span><span><span><span><span><span>因 为一个大型的分布式系统中势必会涉及到各种各样的设备，比如网络交换机，普通</span><span lang="EN-US"><span style="font-family: Calibri;">PC</span></span><span>机，各种型号的网卡，硬盘，内存等等，而这 些东东都在数量非常多的时候，出现错误的概率也会变大，因此我们需要时时刻刻监控系统的状态，而监控也有粒度的粗细之分，粒度粗一点的话，我们需要对整个 应用系统进行监控，比如目前的系统网络流量是多少，内存利用率是多少，</span><span lang="EN-US"><span style="font-family: Calibri;">IO</span></span><span>，</span><span lang="EN-US"><span style="font-family: Calibri;">CPU</span></span><span>的 负载是多少，服务的访问压力是多少，服务的响应时间是多少等这一系列的监控，而细粒度一点的话，我们就需对比如应用中的某个功能，某个</span><span lang="EN-US"><span style="font-family: Calibri;">URL</span></span><span>的 访问量是多，每个页面的</span><span lang="EN-US"><span style="font-family: Calibri;">PV</span></span><span>是 多少，页面每天占用的带宽是多少，页面渲染时间是多少，静态资源比如图片每天占用的带宽是多少等等进行进一步细粒度的监控。因此一个监控系统就变得必不可 少了。</span></span></span></span></span></span></span></span></span></span></span></p>
<p class="MsoNormal" style="text-indent: 18pt; margin: 0cm 0cm 0pt;">
	<span><span><span><span><span><span><span><span><span><span><span>前 面说了一个监控系统的重要性，有了监控系统以后，更重要的是要和预警系统结合起来，比如当某个页面访问量增多的时候，系统能自动预警，某台</span><span lang="EN-US"><span style="font-family: Calibri;">Server</span></span><span>的</span><span lang="EN-US"><span style="font-family: Calibri;">CPU</span></span><span>和 内存占用率突然变大的时候，系统也能自动预警，当并发请求丢失严重的时候，系统也能自动预警等等，这样以来通过监控系统和预警系统的结合可以使得我们能快 速响应系统出现的问题，提高系统的稳定性和可用性。</span></span></span></span></span></span></span></span></span></span></span></p>
<h1 style="margin: 12pt 0cm;">
	<span><span><span><span><span><span><span><span><span><span><span style="font-size: large;"><span>八</span><span style="font-family: Calibri;"> </span><span>配置统一管理</span></span></span></span></span></span></span></span></span></span></span></span></h1>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
	<span><span><span><span><span><span><span><span><span><span><span lang="EN-US"><span><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>一个大型的分布 式应用，一般都是有很多节点构成的，如果每次一个新的节点加入都要更改其它节点的配置，或者每次删除一个节点也要更改配置的话，这样不仅不利于系统的维护 和管理，同时也更加容易引入错误。另外很多时候集群中的很多系统的配置都是一样的，如果不进行统一的配置管理，就需要再所有的系统上维护一份配置，这样会 造成配置的管理维护很麻烦，而通过一个统一的配置管理可以使得这些问题得到很好的解决，当有新的节点加入或者删除的时候，配置管理系统可以通知各个节点更 新配置，从而达到所有节点的配置一致性，这样既方便也不会出错。</span></span></span></span></span></span></span></span></span></span></span></p>
]]></content:encoded>
				</item>			
							<item>
					<title>程序员特有的9个坏习惯</title>
					<link>http://www.phpv.net/html/1712.html</link>
					<comments>http://www.phpv.net/html/1712.html#comment</comments>
					<pubDate>Fri, 09 Jul 2010 14:07:37 +0800</pubDate>
					<dc:creator></dc:creator>
					<category><![CDATA[其它杂谈]]></category>
					<guid isPermaLink="false">http://www.phpv.net/html/1712.html</guid>
					<description><![CDATA[每次陪女朋友看电影看到电影院座位上稀稀落落的人就想做磁盘碎片整理…]]></description>
					<content:encoded><![CDATA[<p>
	　　 如果你是一个<font>程序员</font>, 或者你就读计算机相关专业, 那么你应该能理解下面这些诡异的小习惯是怎么养成的, 或者你本身就有着其中的某些习惯: <br />
	<br />
	　　<strong>0. <font>程序员</font>数数会从0开始数起. </strong><br />
	<br />
	　　例: <font>程序员</font>吵 架的时候会说: &ldquo;我数三下, 你再不闭嘴我就不客气了! 零! 一! 二!&rdquo; 或者列清单的时候编号会从0.开始写. <br />
	<br />
	　　因: array[0]是数组的第一个元素. <br />
	<br />
	　　评: 这个习惯的养成是一个艰难的过程. 多少次的越界, 多少次的循环次数错误让我们深深的记住了从0开始. <br />
	<br />
	　　<strong>1. <font>程序员</font>用肯定和否定 回答选择性的问题. </strong><br />
	<br />
	　　例: 问 &ldquo;您想喝咖啡还是喝茶?&rdquo; <font>程序员</font>答: &ldquo;嗯.&rdquo; <br />
	<br />
	　　因: 当条件或||有一个子句值为真, 则整个语句值为真. <br />
	<br />
	　　评: 这个习惯夸张了一点, 但这的确是<font>程序员</font>思维方式的通病, 用计算机的处理逻辑处理人类问题. 当然这样的回答显然是存在编程错误的, 因为对于这个问题他错误的返回了布尔型的值. 虽然高度怀疑有没有人关心这种回答的结果是怎样, 还是给出一个答案. 如果真的在程序的世界里, 服务员会优先考虑给你咖啡, 如果没有咖啡了, 才会端茶给你. <br />
	<br />
	　　2. <font>程序员</font>普遍患有或曾经患有分号结尾综合症; <br />
	<br />
	　　例: 比如这几行; <br />
	<br />
	　　 因: 大部分程序, 特别是多数<font>程序员</font>的启蒙编程语言C语言是用分号结尾语句的; <br />
	<br />
	　 　评: 换行之前习惯用分号结尾, 这是<font>程序员</font>专属的坏习惯. 还记得编译报的各种诡异的错最后原因总是少了那一个小小的&rdquo;;&rdquo;吗? 这就是这个坏习惯的成因. 据说分号结尾是有典故的, 因为键盘上的分号正好在右手小拇指的位置, 比起句号之类有着得天独厚的地理优势. 当然也有不需要分号结尾的编程语言(比如Ruby还有Python), 刚用起来会因为没有分号结尾而格外纠结. <br />
	<br />
	　　<strong>3. <font>程序员</font>对&rdquo;语言&rdquo;的概念和普通人有差. </strong><br />
	<br />
	　　例: 问: &ldquo;你都会哪些语言?&rdquo; 普通人: &ldquo;我会汉语和英语, 还会一点点法语.&rdquo; <font>程序员</font>: &ldquo;我会C语言, C++ 和 Java, 还会一点点Ruby.&rdquo; <br />
	<br />
	　　因: <font>程序员</font>的世界里没有母语和外语, 只有编程语言. <br />
	<br />
	　　评: 说真的, 程序语言的语法学起来比外语更容易, 拿到一个用没学过的语言写的程序, 你多少可以看懂部分程序. 程序语言没有国界, 是各国<font>程序员</font>交流最好的桥梁. <br />
	<br />
	　 　<strong>4. <font>程序员</font>格格外外的厌恶括号/引号不配对的情形. </strong><br />
	<br />
	　　例: 看到这样的内容 (举个简单的例子(我知道你懂的), 你能表示&rdquo;我很淡定我不抓狂吗? <br />
	<br />
	　　因: 各种不配对问题会导致编译错误. <br />
	<br />
	　 　评: 扫视代码, 对不配对的情况异常敏感, 瞥一眼就能发现哪里少了个右括号. 这种症状在使用那些带自动补全功能的开发环境时变得更为纠结. <br />
	<br />
	　 　<strong>5. <font>程序员</font>认为 千(k) == 1024. </strong><br />
	<br />
	　　例: <font>程序员</font>换算表: 1km == 1024m, 1kg == 1024g. <br />
	<br />
	　　因: 成因很曲折 计算机是二进制的世界 -&gt; 1024是2的10次方 -&gt; 英语里用kilo一词来表示 -&gt; kilo翻译成中文是&rdquo;千&rdquo;, 比如千米, 千克. <br />
	<br />
	　　评: 也许一般人会认为500, 1000是很整的数, 但<font>程序员</font>会觉得512, 1024是很整的数. 不要奇怪, 如果128, 256, 512这种形式看着不够整, 帮你转换成二进制: 10000000, 100000000, 1000000000&hellip; <br />
	<br />
	　　<strong>6. <font>程序员</font>惯用 == 来表示相等的意思. </strong><br />
	<br />
	　　例: 见5. <br />
	<br />
	　　因: 在程序语言中, &ldquo;=&rdquo; 是赋值, &ldquo;==&rdquo; 才用来判断二者是否相等. <br />
	<br />
	　　评: 单等和双等的区别是程序入门必修课, 也是老师爱考的考点. 如果在C语言if语句的判定条件里写了个单等, 编译能通过, 结果却往往不对, 够一个新手查上一阵子的. 当然目前的语言大都考虑到这一点, 防止了这类的误写, 但是单等和双等的差异已经深入每个<font>程序员</font>的 内心. <br />
	<br />
	　　<strong>7. <font>程序员</font>使用&rdquo;//&rdquo;表示&rdquo;请无视这一行文字&rdquo;. </strong><br />
	<br />
	　 　例: 餐厅中. <font>程序员</font>A: &ldquo;我吃鱼香肉丝盖饭, 你吃什么?&rdquo; <br />
	<br />
	　　<font>程序员</font>B: &ldquo;宫保鸡丁盖饭.&rdquo; <br />
	<br />
	　　<font>程序员</font>A 在点菜单写上: <br />
	<br />
	　　鱼香肉丝盖饭 1 <br />
	<br />
	　　宫保鸡丁盖饭 1 <br />
	<br />
	　　<font>程序员</font>B: &ldquo;我还是要牛肉面吧!&rdquo; <br />
	<br />
	　　<font>程序员</font>A 更正点菜单: <br />
	<br />
	　　鱼香肉丝盖饭 1 <br />
	<br />
	　　// 宫保鸡丁盖饭 1 <br />
	<br />
	　　牛肉面 1 <br />
	<br />
	　 　因: 程序中用&rdquo;//&rdquo;为代码加上注释, 程序运行时会无视掉&rdquo;//&rdquo;开头的代码行. <br />
	<br />
	　　评: 如果和一伙<font>程序员</font>在一起时被冷落了, 可以抱怨一句&rdquo;喂喂喂我是被注释掉了吗?&rdquo; 相信一向以幽默感丰富又有爱心著称的<font>程序员</font>们会关注你的. <br />
	<br />
	　　<strong>8. <font>程序员</font>有 中文标点恐惧症. </strong><br />
	<br />
	　　例: 如果你注意到了, 这篇文章自始至终都在使用英文标点, 这就是最好的例子. <br />
	<br />
	　　因: 程序中的全部符号都严格需要是英文半角标点. <br />
	<br />
	　　评: 这个坏习惯是有中国特色的, 中国<font>程序员</font>特 有的. 任何一名优秀的我国<font>程序员</font>都应该可以作到区别中文标点和英文标点. 比如, 和，还有 &rsquo;和 &lsquo;. 真的, 当年初学编程的时候, 诸如 &ldquo;error C2018: unknown character &rsquo;0xa3&prime;&rdquo; 的错误看得还不够多吗! <br />
	<br />
	　　就是这样一群人, 如果你慢吞吞的用电脑他们会急躁的抢过键盘熟练的使用各种快捷键, 他们会对着小孩子讲计算机的三原色是红绿蓝而不是红黄蓝, 他们描述大小距离更偏向于以像素作单位, 陪女朋友看电影看到电影院座位上稀稀落落的人就想做磁盘碎片整理&hellip;抱怨归抱怨, 这不也正是他们的可爱之处吗!</p>
]]></content:encoded>
				</item>			
							<item>
					<title>怎样把自己培养成为一个优秀的程序员 </title>
					<link>http://www.phpv.net/html/1711.html</link>
					<comments>http://www.phpv.net/html/1711.html#comment</comments>
					<pubDate>Fri, 07 May 2010 13:53:26 +0800</pubDate>
					<dc:creator></dc:creator>
					<category><![CDATA[其它杂谈]]></category>
					<guid isPermaLink="false">http://www.phpv.net/html/1711.html</guid>
					<description><![CDATA[从态度、学习、开发流程、用户、编程、调试、团队协作 七方面列举了45条实用经验，帮助你成为一个受人尊敬的好程序员。]]></description>
					<content:encoded><![CDATA[<p>
	&nbsp;</p>
<div class="entry-body">
	<div>
		<div class="item-body">
			<div>
				<p>
					<strong>态度篇</strong></p>
				<p>
					&nbsp;1. 做实事：不要抱怨，发牢骚，指责他人，找出问题所在，想办法解决。对问题和错误，要勇于承担。</p>
				<p>
					&nbsp;2. 欲速则不达：用小聪明、权宜之计解决问题，求快而不顾代码质量，会给项目留下要命的死角。</p>
				<p>
					&nbsp;3. 对事不对人：就事论事，明智、真诚、虚心地讨论问题，提出创新方案。</p>
				<p>
					&nbsp;4. 排除万难，奋勇前进：勇气往往是克服困难的唯一方法。</p>
				<p>
					&nbsp;</p>
				<p>
					<strong>学习篇</strong></p>
				<p>
					&nbsp;5. 跟踪变化：新技术层出不穷并不可怕。坚持学习新技术，读书，读技术杂志，参加技术活动，与人交流。要多理解新词背后的所以然，把握技术大趋势，将新技术用 于产品开发要谨慎。</p>
				<p>
					&nbsp;6. 对团队投资：打造学习型团队，不断提高兄弟们的平均水平。</p>
				<p>
					&nbsp;7. 懂得丢弃：老的套路和技术，该丢，就得丢。不要固步自封。</p>
				<p>
					&nbsp;8. 打破砂锅问到底：不断追问，真正搞懂问题的本质。为什么？应该成为你的口头禅。</p>
				<p>
					&nbsp;9. 把握开发节奏：控制好时间，养成好习惯，不要加班。</p>
				<p>
					&nbsp;</p>
				<p>
					<strong>开发流程篇</strong></p>
				<p>
					&nbsp;10. 让客户做决定：让用户在现场，倾听他们的声音，对业务最重要的决策应该让他们说了算。</p>
				<p>
					&nbsp;11. 让设计指导而不是操纵开发：设计是前进的地图，它指引的是方向，而不是目的本身。设计的详略程度应该适当。</p>
				<p>
					&nbsp;12. 合理地使用技术：根据需要而不是其他因素选择技术。对各种技术方案进行严格地追问，真诚面对各种问题。</p>
				<p>
					&nbsp;13. 让应用随时都可以发布：通过善用持续集成和版本管理，你应该随时都能够编译、运行甚至部署应用。</p>
				<p>
					&nbsp;14. 提早集成，频繁集成：集成有风险，要尽早尽量多地集成。</p>
				<p>
					&nbsp;15. 提早实现自动化部署</p>
				<p>
					&nbsp;16. 使用演示获得频繁反馈</p>
				<p>
					&nbsp;17. 使用短迭代，增量发布</p>
				<p>
					&nbsp;18. 固定价格就意味着背叛承诺：估算应该基于实际的工作不断变化。</p>
				<p>
					&nbsp;</p>
				<p>
					<strong>用户篇</strong></p>
				<p>
					&nbsp;19. 守护天使：自动化单元测试是你的守护天使。</p>
				<p>
					&nbsp;20. 先用它再实现它：测试驱动开发其实是一种设计工具。</p>
				<p>
					&nbsp;21. 不同环境，就有不同问题：要重视多平台问题。</p>
				<p>
					&nbsp;22. 自动验收测试</p>
				<p>
					&nbsp;23. 度量真实的进度：在工作量估算上，不要自欺欺人。</p>
				<p>
					&nbsp;24. 倾听用户的声音：每一声抱怨都隐藏着宝贵的真理。</p>
				<p>
					&nbsp;</p>
				<p>
					<strong>编程篇</strong></p>
				<p>
					&nbsp;25. 代码要清晰地表达意图：代码是给人读的，不要耍小聪明。</p>
				<p>
					&nbsp;26. 用代码沟通：注释的艺术。</p>
				<p>
					&nbsp;27. 动态地进行取舍：记住，没有最佳解决方案。各种目标不可能面面俱到，关注对用户重要的需求。</p>
				<p>
					&nbsp;28. 增量式编程：写一点代码就构建、测试、重构、休息。让代码干净利落。</p>
				<p>
					&nbsp;29. 尽量简单：宁简勿繁。如果没有充足的理由，就不要使用什么模式、原则和特别的技术。</p>
				<p>
					&nbsp;30. 编写内聚的代码：类和组件应该足够小，任务单一。</p>
				<p>
					&nbsp;31. 告知，不要询问：多用消息传递，少用函数调用。</p>
				<p>
					&nbsp;32. 根据契约进行替换：委托往往优于继承。</p>
				<p>
					&nbsp;</p>
				<p>
					<strong>调试篇</strong></p>
				<p>
					&nbsp;33. 记录问题解决日志：不要在同一地方摔倒两次。错误是最宝贵的财富。</p>
				<p>
					&nbsp;34. 警告就是错误：忽视编译器的警告可能铸成大错。</p>
				<p>
					&nbsp;35. 对问题各个击破：分而治之是计算机科学中最重要的思想之一。但是，要从设计和原型阶段就考虑各部分应该能够很好地分离。</p>
				<p>
					&nbsp;36. 报告所有的异常</p>
				<p>
					&nbsp;37. 提供有用的错误信息：稍微多花一点心思，出错的时候，将给你带来极大便利。</p>
				<p>
					&nbsp;</p>
				<p>
					<strong>团队协作篇</strong></p>
				<p>
					&nbsp;38. 定期安排会面时间：常开会，开短会。</p>
				<p>
					&nbsp;39. 架构师必须写代码：不写代码的架构师不是好架构师。好的设计都来自实际编程。编程可以带来深入的理解。</p>
				<p>
					&nbsp;40. 实行代码集体所有制：让开发人员在系统不同区域中不同的模块和任务之间轮岗。</p>
				<p>
					&nbsp;41. 成为指导者：教学相长。分享能提高团队的总体能力。</p>
				<p>
					&nbsp;42. 让大家自己想办法：指引方向，而不是直接提供解决方案。让每个人都有机会在干中学习。</p>
				<p>
					&nbsp;43. 准备好后再共享代码：不要提交无法编译或者没有通过单元测试的代码！</p>
				<p>
					&nbsp;44. 做代码复查：复查对提高代码质量、减少错误极为重要。</p>
				<p>
					&nbsp;45. 及时通报进展与问题：主动通报，不要让别人来问你。</p>
			</div>
		</div>
	</div>
</div>
]]></content:encoded>
				</item>			
							<item>
					<title>大型高性能网站的十项规则</title>
					<link>http://www.phpv.net/html/1710.html</link>
					<comments>http://www.phpv.net/html/1710.html#comment</comments>
					<pubDate>Mon, 19 Apr 2010 12:34:14 +0800</pubDate>
					<dc:creator></dc:creator>
					<category><![CDATA[WEB架构]]></category>
					<guid isPermaLink="false">http://www.phpv.net/html/1710.html</guid>
					<description><![CDATA[总结了国内网络和游戏公司运行后端服务器过程中所得到的实践经验和教训。这些规则适用于日访问量从一万到上百万的大型系统。]]></description>
					<content:encoded><![CDATA[<p>
	<span class="Apple-style-span" style="font-size: medium; ">在我们公司ChinaNetCloud，见 过多种不同类型的网站和系统，有好也有差。其中有些系统拥有良好的服务器/网络架构，并且进行了合理的调整和监控 ；然而一般的系统都会有安全和性能上的 问题，不能良好运行，也无法变得更流行。</span></p>
<p style="text-align: left;">
	<span class="Apple-style-span" style="font-size: medium; ">在中国， 开源的LAMP栈是最流行的网络架构，它使用PHP开发，运行在Apache服务器上，以MySQL作为数据库，所有这些都运行在Linux上。它是个可靠的平台，运行良好，是现在全球最 流行的Internet系统架构。然而，我们很难对其规模进行正确的扩展并保持安全性，因为每个应用层都有其自身的问题、缺陷和最佳实践。我们的工作就是 帮助企业用最低的操作成本来创建并运行高性能的、可伸缩的、安全的系统，因此对于这类问题我们有很丰富的经验。</span></p>
<p style="text-align: left;">
	<span class="Apple-style-span" style="font-size: medium; ">当前的实际情况是，很多网站都是由开发人员 快速而廉价地创建，通常没有任何IT人员或者经理，只是由程序员来管理系统。造成的结果是，虽然花费很低的成本网站就可以开始运行，但是当拥有大量用户、 需要扩展规模的时候，通常就会面临真正的问题。毕竟，中国拥有三亿八千万的Internet用户，如果其中的0.01%访问这个站点，就很容易引发25 万~50万的页面访问量。这些问题在各个级别上都会产生，下面总结的规则是对最一般的问题进行概述，并且说明为什么这些规则如此重要，以及最好采用什么方 法来修正它们。遵循这些建议的站点会提高它的可伸缩性、安全性以及操作上的稳定性。</span></p>
<p style="text-align:
 left;">
	<font size="3"><br />
	</font></p>
<p style="text-align: left;">
	<b><font size="3">使用合适的会话管理<br />
	<span class="Apple-style-span" style="font-weight: normal; font-size: 12px; "><b><font size="3"><span class="Apple-style-span" style="font-weight: normal; ">第 一个想到的扩展系统的方法就是添加更多硬件。例如，使用两台服务器而不是一台。这听着合理，但会产生潜在问题：会话管理。这对Java程序来说是很严重的问题，在PHP中也会产生可延展性问题， 对于数据库的负载尤其如此。</span></font></b></span></font></b></p>
<p style="text-align: left;">
	<span class="Apple-style-span" style="font-size: medium; ">会话被定义为单独的最终用户登录或者连接一 段时间，其中通常会包含多个TCP/IP的HTTP连接、几个Web页面，通常还包括几十个甚至上百个页面元素，如框架、菜单、Ajax更新等。所有这些 HTTP请求都需要知道用户是谁，才能满足安全的要求，并向用户传送适当的内容，因为这些都是会话的组成部分。通常每个会话都会包括相互关联的会话数据， 如用户名、用户ID、历史、购物车、统计资料等等信息。</span></p>
<p style="text-align: left;">
	<span class="Apple-style-span" style="font-size: medium; ">问题在 于，在有两台Web服务器和多个 HTTP连接的情况下，用户流量会在两台服务器之间分配和移动，服务器很难知道用户是谁，并对所有数据进行跟踪，因为每个页面或者页面的组成部分都可能来 自不同的服务器。在PHP中，通常是这样解决的，在第一次连接或登录的时候就创建一个会话ID并将其放在Cookie中，然后这个Cookie会和每个 HTTP请求一起发送。</span></p>
<p style="text-align: left;">
	<span class="Apple-style-span" style="font-size: medium; ">这样做带来一个问题，接下来每段PHP脚本 都需要基于ID来查找会话数据。由于PHP无法在执行过程之间保持状态（这与Java不同），这个会话数据需要存储在某个地方，通常是在数据库中。但是， 如果复杂的页面需要在每个页面载入过程中对其进行十次查找（这是经常要做的），那就意味着每个页面都要执行10次SQL查询，这会导致数据库上很大的负 载。</span></p>
<p style="text-align: left;">
	<font size="3">在前面所举的中国 Internet用户 0.01%的例子中，可能很容易在每秒内仅仅为了管理会话就生成上百个查询。解决方法是一直使用位于Cookie中的会话ID，并且使用像 Memcached之类的服务来缓存会话数据以获得高性能。</font></p>
<p style="text-align: left;">
	<span class="Apple-style-span" style="font-size: medium; ">还要注 意其中存在安全性的问题，因为黑客可 以伪造另一个用户的会话ID，这是很容易找到或看到的，特别是在公用的Wi-Fi中。解决方法是对会话ID进行恰当的加密或者签名，并将其与时间区间、 IP地址以及其他关键信息 像浏览器或者其他细节相绑定。在Internet上有很多不错的关于良好的会话管理的例子，你可以根据需要找到最适合的。</span></p>
<p style="text-align: left;">
	&nbsp;</p>
<p style="text-align: left;">
	<b><font size="3">总是要考虑安全性<br />
	<span class="Apple-style-span" style="font-weight: normal; ">尽管编写像防止SQL注入和登录安全之类的 代码涉及很多安全问题，但不幸的是，几乎没有人考虑过安全性，而那些考虑到的人也没有对其进行很好地理解。而本文要关注的是操作性的系统安全。对于这类安 全，我们的焦点集中在三个安全领域：防火墙、运行的用户以及文件访问权限。</span></font></b></p>
<p style="text-align: 
left;">
	<span class="Apple-style-span" style="font-size: medium; ">除了配置专门的硬件防火墙（像Cisco的 ASA）之外，所有服务器都还应该运行像Iptables之类的防火墙，它会保护服务器免受其他威胁和攻击。这些威胁和攻击可能来自公共的 Internet、其他服务器或本地服务器，也包括使用VPN或者SSH通道的开发和操作人员。我们仅对指定的IP开放确实需要的端口。Iptables 可能会很复杂，但是有很多不错的模板，我们通常可以使用它们来帮助客户创建Iptables。例如，默认的RedHat或者CentOS防火墙的配置说明 只有10行，显然并不实用。我们最佳实践的Iptables配置大概有5页，这其中包含了Linux所能提供的最高级的安全防范。</span></p>
<p style="text-align: left;">
	<span class="Apple-style-span" style="font-size: medium; ">所有公用的服务，都应该运行在专门的用户 下，如Apache。切记永远都不要使用Root用户运行，因为这会让任何闯入到Apache的用户接管整个服务器。如果Apache只是运行在 Apache用户下或者运行在Nobody下，那么闯入Apache就不是一件容易的事情了。</span></p>
<p style="text-align: left;">
	<font size="3">Web服务器运行或者服务的文件 （像.php和.html文件）对于Web服务器的用户应该是不可写的。这意味着Apache或者Nginx用户不应该拥有Web目录的写权限。有很多方 法都可以做到这一点，而最简单的就是将这些文件为其他用户所有，然后让Apache/Nginx等用户归属于能够使用640权限读取文件的组中。这会防范 几乎所有的黑客和针对页面的攻击。</font></p>
<p style="text-align: left;">
	<font size="3">此 外，永远不要使用Ftp来上传文件，特别 是在公用的Wi-Fi环境中，因为在其中黑客很容易盗取用户名和密码。取而代之的是使用Sftp会更加安全。另外，每个雇员都应该拥有自己的用户ID和随 机密码。</font></p>
<p style="text-align: left;">
	&nbsp;</p>
<p style="text-align: left;">
	<b><font size="3">使用标准的路径和安装配置</font></b></p>
<p style="text-align: left;">
	<span class="Apple-style-span" style="font-size: medium; ">一个令人讨厌的部署问题是，开发者很少考虑 他们的软件会被部署到生产Web服务器的什么位置，以及如何部署。我们看到过许多大型的系统将它们的PHP代码部署在/home/xiaofeng或者 /web/code路径下。事实上，这两个路径都是非常不标准的，并且会带来操作和安全性的问题。当这些系统从开发环境转移到测试环境再到生产环境中时， 因为每个安装配置都是非标准的，所以经常会出现问题，这时就需要开发者调整才能够正常工作。</span></p>
<p style="text-align: left;">
	<span class="Apple-style-span" style="font-size: medium; ">你应该总是使用标准的安装包和二进制文件来 安装像Apache之类的服务器。不要从源代码编译或者安装Tarball，因为这会导致长期稳定性和管理上的问题，另外在服务器上安装多个不同的版本也 会造成混淆。</span></p>
<p style="text-align: left;">
	<span class="Apple-style-span" style="font-size: medium; ">Web 站点应该总是在指定的平台和 Linux发布的标准路径下进行测试和部署 ，像 RedHat 或者CentOS下的/var/www/html路径。这有助于对系统进行有效的权限管 理、备份、配置、监控以及其他操作。</span></p>
<p style="text-align: left;">
	<font size="3">Web 服务器的日志应该存放在/var /logs或者/var/logs/app_name下，而不应该位于主代码区域。这样做的原因不仅仅是因为这些标准的路径很重要，更应该关注的是，恰当 地配置服务器会将/var配置为分离的文件系统。如果应用程序突然写入了大量日志并占用所有磁盘空间，由于我们做了以上的配置就不会导致系统崩溃，或者其 他严重的问题。如果日志位于其他位置，就可能会产生问题。</font></p>
<p style="text-align: left;">
	<font size="3"><span class="Apple-style-span" style="font-size: 12px; "><b><font size="3">总是使用日志<br />
	<span class="Apple-style-span" style="font-weight: normal; "><br />
	在Web系统中做多少日志都不为过。所有系 统都应该将重要的数据写入到日志中，不管是它们自己的日志还是系统的Syslog。Cron的Job以及其他Shell脚本或者C语言的程序，对日志都有 相应标准以及简单的函数。在Shell脚本中，只需要使用 Logger命令就可以实现日志的写入。在脚本启动/停止、重要的脚本执行以及实时数据产生的 情况下都要执行写入日志操作。这样出现问题的时候，查看主要的系统日志就可以很容易地看到发生了什么。</span></font></b></span></font></p>
<p style="text-align: left;">
	<span class="Apple-style-span" style="font-size: medium; ">大型系统经常会使用专门的工具如 Local5来记录日志，并配置Syslog或者Syslog-ng来将其存放在单独的文件中，这样会更容易使用。需要注意的是，Syslog工具和 Logger（以及任何Syslog调用）默认优先使用user.notice，如有必要，你可以对其进行调整。</span></p>
<p style="text-align: left;">
	<span class="Apple-style-span" style="font-size: medium; ">一个好的系统会对程序进行配置，用来打开或 者关闭日志，并可以选择在每模块或者功能的级别上应用不同级别的日志。这使得我们可以记录非常详细和强大的日志，用来分析和调试在生产操作中所发生的问 题。</span></p>
<p style="text-align: left;">
	<font size="3"><br />
	</font></p>
<div>
	<a href="http://www.programmer.com.cn/wp-content/uploads/2010/04/%E5%A4%A7%E5%9E%8B%E7%BD%91%E7%AB%99%E7%9A%84%E5%8D%81%E9%A1%B9%E8%A7%84%E5%88%99.gif" target="_blank"><img alt="大型网站的十项规则" height="386" src="http://www.programmer.com.cn/wp-content/uploads/2010/04/%E5%A4%A7%E5%9E%8B%E7%BD%91%E7%AB%99%E7%9A%84%E5%8D%81%E9%A1%B9%E8%A7%84%E5%88%99.gif" title="大型网站的十项规则" width="550" /></a>
	<p>
		大型高性能网站的十项规则</p>
	<p>
		&nbsp;</p>
</div>
<p style="text-align: left;">
	<b><font size="3">使用良好的数据库设计和SQL</font></b></p>
<p style="text-align: left;">
	<span class="Apple-style-span" style="font-size: medium; ">在任何系统中，数据库通常是最大的性能瓶 颈。而影响数据库性能的最大两个问题是数据库设计和SQL代码质量。很多系统都拥有良好的或者至少是可用的数据库设计，但由于没有经过适当的性能测 试，SQL代码质量通常都会很差。这样的SQL代码在开发环境中可能运行很快，因为其中只有小数据集和最小的负载。但是当成千上万的用户同时读取数据库中 上百万条记录的时候，它就很可能会崩溃。</span></p>
<p style="text-align: left;">
	<span class="Apple-style-span" style="font-size: medium; ">不幸的 是，这些问题一开始并不明显，直到系 统增大、突然开始崩溃的时候才会显现出来。在增大的过程中，数据库系统看起来运行得很快（因为数据都位于内存中，而且很少有并发的查询），并且对用户的响 应也很快，但实际上它的内部运行效率很低。这并不重要，我们关注的是在系统增大并遇到性能问题之前找到这些问题并加以解决。</span></p>
<p style="text-align: left;">
	<span class="Apple-style-span" style="font-size: medium; ">关于这个问题有很多不错的书和站点进行了解 析，其中的关键工具包括慢查询日志、INNODB状态系统，以及描述当前性能的MySQL统计信息。我们见到过很多系统每秒会读取500,000条数据， 这是出现SQL问题的明显预兆，但公司往往对其一无所知直到服务器开始崩溃。</span></p>
<p style="text-align: 
left;">
	<span class="Apple-style-span" style="font-size: medium; ">MySQL系统应该对所有数据使用 INNODB存储引擎，因为INNODB与之前的MyISAM相比，运行得更快、更稳定，并且管理性能和备份工作也更加容易和快捷。在主配置文件 中，INNODB应该被设置为默认的数据库引擎，并且系统应该不时地进行检查，看是否意外创建了MyISAM的表。</span></p>
<p style="text-align: left;">
	<b><font size="3">总要拥有良好的DB配置和备份</font></b></p>
<p style="text-align: left;">
	<span class="Apple-style-span" style="font-size: medium; ">很多公司都没有良好的备份机制，也不知道如 何恰当地完成这项工作。MySQL的Dump是不够的，因为最好的备份方法是使用LVM快照和INNODB对系统进行热备份，从而得到超快的速度和超高的 可靠性。</span></p>
<p style="text-align: left;">
	<span class="Apple-style-span" style="font-size: medium; ">另外，在将所有备份文件从服务器上转移出来 之前要进行压缩和加密。另外还要确保拥有设计合理的MySQL配置。MySQL默认安装使用说明中只有5~10行关于配置的说明，这根本不适合开发使用。 而我们提供给客户的最佳实践文档足足有10页那么长。文档中大约有100种有用的关于安全、性能和稳定性问题的设定，包括防止数据败坏，其中很多设定都是 非常重要的。</span></p>
<p style="text-align: left;">
	<b><font size="3">使用读/写数据库分离</font></b></p>
<p style="text-align: left;">
	<span class="Apple-style-span" style="font-size: medium; ">随着系统变得越来越庞大，特别是当它们拥有 很差的SQL时，一台数据库服务器通常不足以处理负载。但是多个数据库意味着重复，除非你对数据进行了分离。更一般地，这意味着建立主/从副本系统，其中 程序会对主库编写所有的Update、Insert和Delete变更语句，而所有Select的数据都读取自从数据库（或者多个从数据库）。</span></p>
<p style="text-align: left;">
	<span class="Apple-style-span" style="font-size: medium; ">尽管概念上很简单，但是想要合理、精确地实 现并不容易，这可能需要大量的代码工作。因此，即便在开始时使用同一台数据库服务器，也要尽早计划在PHP中使用分离的DB连接来进行读写操作。如果正确 地完成该项工作，那么系统就可以扩展到2台、3台甚至12台服务器，并具备高可用性和稳定性。</span></p>
<p style="text-align: left;">
	<span style="font-style: normal;"><b><font size="3">使用类似Memcached之类的数据库缓存</font></b></span></p>
<p style="text-align: left;">
	<span class="Apple-style-span" style="font-size: medium; ">即便有了好的数据库设计、SQL和读写分 离，大型的系统仍然需要更快的性能，特别是对会话状态、好友列表以及BBS文字之类的东西。为了达到这个目的，我们可以使用像MemCached之类的数 据缓存，它是一个高性能的简单数据缓存，已经被所有最大型的站点使用。但是要小心的是，不要100%依赖于一台Memcache服务器来提高性能，因为如 果那台服务器崩溃了，就会破坏整个系统的性能。在这种情况下，应该使用2~3台Memcache服务器形成簇集架构，并且有选择地包含一个缓存准备过程， 如果缓存服务器重启，需要重新载入数据，它能够快速地载入缓存。</span></p>
<p style="text-align: left;">
	<span class="Apple-style-span" style="font-size: medium;"><font class="Apple-style-span" size="3"><span class="Apple-style-span" style="font-size: 12px;"><br />
	</span></font></span></p>
<p style="text-align: left;">
	<b><font size="3">构建测试和开发环境</font></b></p>
<p style="text-align: left;">
	<span class="Apple-style-span" style="font-size: medium; ">很多公司只有开发者的桌面系统和他们的生产 服务器。当系统变得越来越大、越来越复杂时，测试和管理代码就会导致严重的问题。最佳的实践是拥有两个测试系统，一个用于开发者的代码和功能的整合测试， 另一个要与生产环境完全一致，从而更容易向生产环境平滑地过渡。幸运的是，现在使用云计算（或者私有云）可以轻松达到这一点。一个5~10台服务器的生产 环境，可以很容易地在办公室或者IDC中使用一台服务器来复制，从而用于测试，而这台服务器我们可以用于多个客户的项目。</span></p>
<p style="text-align: left;">
	<span class="Apple-style-span" style="font-size: medium;"><font class="Apple-style-span" size="3"><span class="Apple-style-span" style="font-size: 12px;"><br />
	</span></font></span></p>
<p style="text-align: left;">
	<b><font size="3">使 用版本控制</font></b></p>
<p style="text-align: left;">
	<font size="3">最后，要对一切使用版本控制，包括测试和生 产环境的部署。很多开发者都使用SVN或者类似的方法。在理想状态下，这些方法可以被用于所有代码、脚本、HTML、图片、配置、文档和测试。版本控制应 该是代码转移到测试环境的必经之路，而不是简单地复制或者使用tar文件，因为这二者都是不可靠的。开发者应该将所有一切都签入，打上标签，然后将它们签 出到测试系统。如果所有都没问题，那么它们会将该版本签出到生产环境。</font></p>
<p style="text-align: 
left;">
	<b><font size="3">总结</font></b></p>
<p style="text-align: left;">
	<font size="3">不管 是在开发还是在运营过程中，创建可靠的 高性能Web系统都有很多应该注意的事项。本文试图从可操作性和可靠性的角度讨论最重要的几点。当你构建和管理站点的时候，请不要忘了这些重要的问题。遵 循这些规则会有助于确保系统长久、良好地运行。</font></p>
<p style="text-align: left;">
	<b><font size="3">作者简介：</font></b></p>
<p style="text-align: left;">
	<font size="3">Steve Mushero，ChinaNetCloud 公司联合创始人、CEO兼CTO，拥有全球20多年的技术管理经验。曾担任土豆网、Intermind和 Advanced Management Systems等多家企业CTO</font></p>
<p style="text-align: 
left;">
	<b><font size="3">译者简介：</font></b></p>
<p style="text-align: left;">
	<font size="3">侯伯薇，生于凤城，学在春城，做过国内和对 日项目，现在大连某保险公司工作。乐于钻研技术，同时注重业务知识，勤于思考，愿意与人交流和分享。</font></p>
]]></content:encoded>
				</item>			
							<item>
					<title>Save Mysql  拯救MySQL! </title>
					<link>http://www.phpv.net/html/1709.html</link>
					<comments>http://www.phpv.net/html/1709.html#comment</comments>
					<pubDate>Thu, 28 Jan 2010 19:22:41 +0800</pubDate>
					<dc:creator></dc:creator>
					<category><![CDATA[数据库技术]]></category>
					<guid isPermaLink="false">http://www.phpv.net/html/1709.html</guid>
					<description><![CDATA[为阻止Oracle收购Sun，在欧盟似乎已决定批准这项70亿美元的收购案之后，MySQL数据库创始人开始寻求中国和俄罗斯帮助。

在一封给中国 MySQL用户的邮件中写道 “亲爱的拯救MySQL的中国签名支持者，欧盟可能无法拯救MySQL, 中国和俄罗斯可能是拯救MySQL的希望之所在。中国拥有强大、独立以及自信的反垄断主管机关，因此，我本人在此请求您的帮助。对于您的签名，我们深表感谢。如果可以的话，我们需要您的进一步帮助……”]]></description>
					<content:encoded><![CDATA[<p>
	为阻止Oracle收购Sun，在欧盟似乎已决定批准这项70亿美元的收购案之后，MySQL数据库创始人开始寻求中国和俄罗斯帮助。</p>
<p>
	在一封给中国 MySQL用户的邮件中写道 &ldquo;亲爱的拯救MySQL的中国签名支持者，欧盟可能无法拯救MySQL, 中国和俄罗斯可能是拯救MySQL的希望之所在。中国拥有强大、独立以及自信的反垄断主管机关，因此，我本人在此请求您的帮助。对于您的签名，我们深表感谢。如果可以的话，我们需要您的进一步帮助&hellip;&hellip;&rdquo;</p>
<p>
	<br />
	下面是具体的参与方法<br />
	点击这个链接并且填写自己的信息提交即可<br />
	<a href="http://helpmysql.org/cn/petition" target="_blank">http://helpmysql.org/cn/petition</a></p>
<p>
	&nbsp;</p>
<div class="header">
	<a href="http://helpmysql.org/cn"><img alt="" src="http://helpmysql.org/fwk/ml/10001094" /></a></div>
<p>
	&nbsp;</p>
<p>
	FAQ:</p>
<p>
	----------------------------------</p>
<p>
	<strong>我们还有多少时间？</strong></p>
<p>
	时间紧迫，但您仍然可以帮上忙。如果已经太晚（不论好还是坏），我们将立即停用请愿书，并在本网站每一页面上公布结果。</p>
<p>
	在我们通知您之前，请不要相信已经结束的任何说法。这些说法可能是试图破坏本次活动的某些人散布的。</p>
<p>
	本次活动网站于2009年12月28日启动。我们越早赢得大量支持者越好。关键的日期是2010年1月4日。那一天（明年的第一个工作日）我们计划 正式向监管者、其他政府机构、议会和记者提交请愿书。之后，我们将继续收集支持，直到程序结束，而且表示持续的支持也很重要。我们可能在2010年1月或 者可能2月份进行请愿书的多次提交。</p>
<p>
	<strong>活动为何是全球性的？</strong></p>
<p>
	甲骨文需要在全球所有主要市场取得审批。因此，我们将在世界不同地区提交请愿书。</p>
<p>
	一般而言，监管者会把数据库市场的地理范围界定为全球性的。只要想想MySQL，显然就明白了：人们可以在全球各地下载或获取MySQL，并在各地使用它。因此，您的签名支持甚至会到达您的国家以外的世界其他地方的监管者面前。</p>
<p>
	<strong>我们需要多少签名才能成功？</strong></p>
<p>
	没有特定限值。这不是事先就知道100,000签名者就能启动政治程序（根据某些法律）的请愿。这是有关MySQL用户的关注和希望达成令MySQL今后独立于甲骨文的真正解决方案（或者至少依赖程度更小）的表达。</p>
<p>
	这不仅仅是关于绝对数字的问题，而是如何能尽快签字，而且签字是否始终以较高速度增长的问题。您越快签字，越快让其他人知道就越好。</p>
<p>
	<strong>如何处理我的数据？我能相信你吗？</strong></p>
<p>
	我们知道如您支持本次活动那么您就信任我们，我们将证明我们是值得信赖的。</p>
<p>
	我们有明确的资料保密声明，请见<a href="http://helpmysql.org/cn/faq/link" page="" petition="" to="">请愿书页</a>，说明您的数据将只能用于提交请愿书给监管者、其他政府机关、议会和重要、声誉良好的新闻机构记者。如我们向您发送了有关本次活动的信息，您可点击取消链接，这样您将不会收到我们的任何其他电子邮件。</p>
<p>
	<strong>你们如何向监管者、议会和新闻机构提交请愿书？谁会看到请愿书？</strong></p>
<p>
	有时候请愿书是以打印文件的方式提交，以表明其数量庞大。但是，为了环保考虑，我们可能选择以电子格式提交大多数的请愿书。监管者、议会和重要、著 名的新闻媒体会收到它们，其中附带了不得以任何与本次活动无关的方式使用数据的明确要求，并且，新闻媒体必须签署接收上述要求的文件，并将不被允许从请愿 书中引用任何姓名和其他唯一或范围较窄的识别数据，除非他们从签字人处收到书面明示许可（包括电子邮件方式），允许在报道中提及。</p>
<p>
	处理本次案件的监管者将把请愿书放入甲骨文/太阳微电子案卷中。对于查看该卷宗有特殊的规定。例如，欧盟甲骨文律师当然会有权看到请愿书。因此，有必要让请愿书具有真正的震撼效果。</p>
<p>
	我们不要求请愿书中提供任何特殊的敏感信息，如您决定填写其中内容的，我们也不希望您在公共或私人评论字段中提供任何敏感信息。</p>
<p>
	<strong>如何能最有效地帮助请愿成功？</strong></p>
<p>
	显然最好的第一步就是您在请愿书上签字。</p>
<p>
	在<a href="http://helpmysql.org/cn/promote">帮助倡议</a> 部分，您可找到进一步说明和材料，以及在网站上设置的标语。</p>
<p>
	我们相信您知道其他专业的MySQL用户，并且有办法鼓励他们在请愿书上签字。</p>
<p>
	<strong>我需要现在亲自写信给欧盟吗？或者写信给本国的反垄断机构或议会，例如欧洲议会？</strong></p>
<p>
	我们认为本次活动将产生大量的回复，当然对于各个机构而言处理完整的请愿书更加容易一些。我们尽可能通过互联网进行号召，包括通过电子邮件，除非通过直接联系能够取得明显不同的良好效果。</p>
<p>
	如果您可以代表10名或以上员工规模的公司发言，并且MySQL对贵公司很重要，或者如果您可以代表100名或以上员工规模的公司发言，而且贵公司 把MySQL用于重大业务目的，请联系贵国反垄断机构，并表达您关于甲骨文收购MySQL计划的关注。如您需要任何帮助，请使用联系表向我们提问。</p>
]]></content:encoded>
				</item>			
							<item>
					<title>通过分区（Partition）提升MySQL性能</title>
					<link>http://www.phpv.net/html/1708.html</link>
					<comments>http://www.phpv.net/html/1708.html#comment</comments>
					<pubDate>Fri, 27 Nov 2009 10:49:16 +0800</pubDate>
					<dc:creator>抽烟的蚊子</dc:creator>
					<category><![CDATA[数据库技术]]></category>
					<guid isPermaLink="false">http://www.phpv.net/html/1708.html</guid>
					<description><![CDATA[数据库分区是一种物理数据库设计技术，DBA和数据库建模人员对其相当熟悉。虽然分区技术可以实现很多效果，但其主要目的是为了在特定的SQL操作中减少数据读写的总量以缩减响应时间。]]></description>
					<content:encoded><![CDATA[什么是数据库分区？<br><br>数据库分区是一种物理数据库设计技术，DBA和数据库建模人员对其相当熟悉。虽然分区技术可以实现很多效果，但其主要目的是为了在特定的SQL操作中减少数据读写的总量以缩减响应时间。<br><br>分区主要有两种形式：//这里一定要注意行和列的概念（row是行，column是列）<br><br>1. 水平分区（Horizontal Partitioning）这种形式分区是对表的行进行分区，通过这样的方式不同分组里面的物理列分割的数据集得以组合，从而进行个体分割（单分区）或集体分割（1个或多个分区）。所有在表中定义的列在每个数据集中都能找到，所以表的特性依然得以保持。<br><br>举个简单例子：一个包含十年发票记录的表可以被分区为十个不同的分区，每个分区包含的是其中一年的记录。（朋奕注：这里具体使用的分区方式我们后面再说，可以先说一点，一定要通过某个属性列来分割，譬如这里使用的列就是年份）<br><br>2. 垂直分区（Vertical Partitioning） 这种分区方式一般来说是通过对表的垂直划分来减少目标表的宽度，使某些特定的列 被划分到特定的分区，每个分区都包含了其中的列所对应的行。<br><br>举个简单例子：一个包含了大text和BLOB列的表，这些text和BLOB列又不经常被访问，这时候就要把这些不经常使用的text和BLOB了划分到另一个分区，在保证它们数据相关性的同时还能提高访问速度。<br><br>在数据库供应商开始在他们的数据库引擎中建立分区（主要是水平分区）时，DBA和建模者必须设计好表的物理分区结构，不要保存冗余的数据（不同表中同时都包含父表中的数据）或相互联结成一个逻辑父对象（通常是视图）。这种做法会使水平分区的大部分功能失效，有时候也会对垂直分区产生影响。<br><br>在MySQL 5.1中进行分区<br><br>MySQL5.1中最激动人心的新特性应该就是对水平分区的支持了。这对MySQL的使用者来说确实是个好消息，而且她已经支持分区大部分模式：<br><br>Range（范围） – 这种模式允许DBA将数据划分不同范围。例如DBA可以将一个表通过年份划分成三个分区，80年代（1980’s）的数据，90年代（1990’s）的数据以及任何在2000年（包括2000年）后的数据。<br><br>Hash（哈希） – 这中模式允许DBA通过对表的一个或多个列的Hash Key进行计算，最后通过这个Hash码不同数值对应的数据区域进行分区，。例如DBA可以建立一个对表主键进行分区的表。<br><br>Key（键值） – 上面Hash模式的一种延伸，这里的Hash Key是MySQL系统产生的。<br><br>List（预定义列表） – 这种模式允许系统通过DBA定义的列表的值所对应的行数据进行分割。例如：DBA建立了一个横跨三个分区的表，分别根据2004年2005年和2006年值所对应的数据。<br><br>Composite（复合模式） - 很神秘吧，哈哈，其实是以上模式的组合使用而已，就不解释了。举例：在初始化已经进行了Range范围分区的表上，我们可以对其中一个分区再进行hash哈希分区。<br><br>分区带来的好处太多太多了，有多少？俺也不知道，自己猜去吧，要是觉得没有多少就别用，反正俺也不求你用。不过在这里俺强调两点好处：<br><br>性能的提升（Increased performance） - 在扫描操作中，如果MySQL的优化器知道哪个分区中才包含特定查询中需要的数据，它就能直接去扫描那些分区的数据，而不用浪费很多时间扫描不需要的地方了。需要举个例子？好啊，百万行的表划分为10个分区，每个分区就包含十万行数据，那么查询分区需要的时间仅仅是全表扫描的十分之一了，很明显的对比。同时对十万行的表建立索引的速度也会比百万行的快得多得多。如果你能把这些分区建立在不同的磁盘上，这时候的I/O读写速度就“不堪设想”（没用错词，真的太快了，理论上100倍的速度提升啊，这是多么快的响应速度啊，所以有点不堪设想了）了。<br><br>对数据管理的简化（Simplified data management） - 分区技术可以让DBA对数据的管理能力提升。通过优良的分区，DBA可以简化特定数据操作的执行方式。例如：DBA在对某些分区的内容进行删除的同时能保证余下的分区的数据完整性(这是跟对表的数据删除这种大动作做比较的)。<br><br>此外分区是由MySQL系统直接管理的，DBA不需要手工的去划分和维护。例如：这个例如没意思，不讲了，如果你是DBA，只要你划分了分区，以后你就不用管了就是了。<br><br>站在性能设计的观点上，俺们对以上的内容也是相当感兴趣滴。通过使用分区和对不同的SQL操作的匹配设计，数据库的性能一定能获得巨大提升。下面咱们一起用用这个MySQL 5.1的新功能看看。<br><br>下面所有的测试都在Dell Optiplex box with a Pentium 4 3.00GHz processor, 1GB of RAM机器上（炫耀啊……），Fedora Core 4和MySQL 5.1.6 alpha上运行通过。<br><br>如何进行实际分区<br><br>看看分区的实际效果吧。我们建立几个同样的MyISAM引擎的表，包含日期敏感的数据，但只对其中一个分区。分区的表（表名为part_tab）我们采用Range范围分区模式，通过年份进行分区：<br><br><br><br>&nbsp;&nbsp; 1. mysql&gt; CREATE TABLE part_tab<br>&nbsp;&nbsp; 2. -&gt; ( c1 int default NULL,<br>&nbsp;&nbsp; 3. -&gt; c2 varchar(30) default NULL,<br>&nbsp;&nbsp; 4. -&gt; c3 date default NULL<br>&nbsp;&nbsp; 5. -&gt;<br>&nbsp;&nbsp; 6. -&gt; ) engine=myisam<br>&nbsp;&nbsp; 7. -&gt; PARTITION BY RANGE (year(c3)) (PARTITION p0 VALUES LESS THAN (1995),<br>&nbsp;&nbsp; 8. -&gt; PARTITION p1 VALUES LESS THAN (1996) , PARTITION p2 VALUES LESS THAN (1997) ,<br>&nbsp;&nbsp; 9. -&gt; PARTITION p3 VALUES LESS THAN (1998) , PARTITION p4 VALUES LESS THAN (1999) ,<br>&nbsp; 10. -&gt; PARTITION p5 VALUES LESS THAN (2000) , PARTITION p6 VALUES LESS THAN (2001) ,<br>&nbsp; 11. -&gt; PARTITION p7 VALUES LESS THAN (2002) , PARTITION p8 VALUES LESS THAN (2003) ,<br>&nbsp; 12. -&gt; PARTITION p9 VALUES LESS THAN (2004) , PARTITION p10 VALUES LESS THAN (2010),<br>&nbsp; 13. -&gt; PARTITION p11 VALUES LESS THAN MAXVALUE );<br>&nbsp; 14. Query OK, 0 rows affected (0.00 sec) <br><br>注意到了这里的最后一行吗？这里把不属于前面年度划分的年份范围都包含了，这样才能保证数据不会出错，大家以后要记住啊，不然数据库无缘无故出错你就爽了。那下面我们建立没有分区的表（表名为no_part_tab）：<br><br><br>&nbsp;&nbsp; 1. mysql&gt; create table no_part_tab<br>&nbsp;&nbsp; 2. -&gt; (c1 int(11) default NULL,<br>&nbsp;&nbsp; 3. -&gt; c2 varchar(30) default NULL,<br>&nbsp;&nbsp; 4. -&gt; c3 date default NULL) engine=myisam;<br>&nbsp;&nbsp; 5. Query OK, 0 rows affected (0.02 sec) <br><br>下面咱写一个存储过程（感谢Peter Gulutzan给的代码，如果大家需要Peter Gulutzan的存储过程教程的中文翻译也可以跟我要，chenpengyi◎gmail.com），它能向咱刚才建立的已分区的表中平均的向每个分区插入共8百万条不同的数据。填满后，咱就给没分区的克隆表中插入相同的数据：<br><br><br>&nbsp;&nbsp; 1. mysql&gt; delimiter //<br>&nbsp;&nbsp; 2. mysql&gt; CREATE PROCEDURE load_part_tab()<br>&nbsp;&nbsp; 3. -&gt; begin<br>&nbsp;&nbsp; 4. -&gt; declare v int default 0;<br>&nbsp;&nbsp; 5. -&gt; while v &lt; 8000000<br>&nbsp;&nbsp; 6. -&gt; do<br>&nbsp;&nbsp; 7. -&gt; insert into part_tab<br>&nbsp;&nbsp; 8. -&gt; values (v,’testing partitions’,adddate(’1995-01-01′,(rand(v)*36520) mod 3652));<br>&nbsp;&nbsp; 9. -&gt; set v = v + 1;<br>&nbsp; 10. -&gt; end while;<br>&nbsp; 11. -&gt; end<br>&nbsp; 12. -&gt; //<br>&nbsp; 13. Query OK, 0 rows affected (0.00 sec)<br>&nbsp; 14. mysql&gt; delimiter ;<br>&nbsp; 15. mysql&gt; call load_part_tab();<br>&nbsp; 16. Query OK, 1 row affected (8 min 17.75 sec)<br>&nbsp; 17. mysql&gt; insert into no_part_tab select * from part_tab;<br>&nbsp; 18. Query OK, 8000000 rows affected (51.59 sec)<br>&nbsp; 19. Records: 8000000 Duplicates: 0 Warnings: 0 <br><br>表都准备好了。咱开始对这两表中的数据进行简单的范围查询吧。先分区了的，后没分区的，跟着有执行过程解析（MySQL Explain命令解析器），可以看到MySQL做了什么：<br><br><br><br>&nbsp;&nbsp; 1. mysql&gt; select count(*) from no_part_tab where<br>&nbsp;&nbsp; 2. -&gt; c3 &gt; date ‘1995-01-01′ and c3 &lt; date ‘1995-12-31′;<br>&nbsp;&nbsp; 3. +———-+<br>&nbsp;&nbsp; 4. | count(*) |<br>&nbsp;&nbsp; 5. +———-+<br>&nbsp;&nbsp; 6. | 795181 |<br>&nbsp;&nbsp; 7. +———-+<br>&nbsp;&nbsp; 8. 1 row in set (38.30 sec)<br>&nbsp;&nbsp; 9. mysql&gt; select count(*) from part_tab where<br>&nbsp; 10. -&gt; c3 &gt; date ‘1995-01-01′ and c3 &lt; date ‘1995-12-31′;<br>&nbsp; 11. +———-+<br>&nbsp; 12. | count(*) |<br>&nbsp; 13. +———-+<br>&nbsp; 14. | 795181 |<br>&nbsp; 15. +———-+<br>&nbsp; 16. 1 row in set (3.88 sec)<br>&nbsp; 17. mysql&gt; explain select count(*) from no_part_tab where<br>&nbsp; 18. -&gt; c3 &gt; date ‘1995-01-01′ and c3 &lt; date ‘1995-12-31′\G<br>&nbsp; 19. *************************** 1. row ***************************<br>&nbsp; 20. id: 1<br>&nbsp; 21. select_type: SIMPLE<br>&nbsp; 22. table: no_part_tab<br>&nbsp; 23. type: ALL<br>&nbsp; 24. possible_keys: NULL<br>&nbsp; 25. key: NULL<br>&nbsp; 26. key_len: NULL<br>&nbsp; 27. ref: NULL<br>&nbsp; 28. rows: 8000000<br>&nbsp; 29. Extra: Using where<br>&nbsp; 30. 1 row in set (0.00 sec)<br>&nbsp; 31. mysql&gt; explain partitions select count(*) from part_tab where<br>&nbsp; 32. -&gt; c3 &gt; date ‘1995-01-01′ and c3 &lt; date ‘1995-12-31′\G<br>&nbsp; 33. *************************** 1. row ***************************<br>&nbsp; 34. id: 1<br>&nbsp; 35. select_type: SIMPLE<br>&nbsp; 36. table: part_tab<br>&nbsp; 37. partitions: p1<br>&nbsp; 38. type: ALL<br>&nbsp; 39. possible_keys: NULL<br>&nbsp; 40. key: NULL<br>&nbsp; 41. key_len: NULL<br>&nbsp; 42. ref: NULL<br>&nbsp; 43. rows: 798458<br>&nbsp; 44. Extra: Using where<br>&nbsp; 45. 1 row in set (0.00 sec) <br><br>从上面结果可以容易看出，设计恰当表分区能比非分区的减少90％的响应时间。而命令解析Explain程序也告诉我们在对已分区的表的查询过程中仅对第一个分区进行了扫描，其他都跳过了。<br>哔厉吧拉，说阿说……反正就是这个分区功能对DBA很有用拉，特别对VLDB和需要快速反应的系统。<br><br>对Vertical Partitioning的一些看法<br><br>虽然MySQL 5.1自动实现了水平分区，但在设计数据库的时候不要轻视垂直分区。虽然要手工去实现垂直分区，但在特定场合下你会收益不少的。例如在前面建立的表中，VARCHAR字段是你平常很少引用的，那么对它进行垂直分区会不会提升速度呢？咱们看看测试结果：<br><br><br><br>&nbsp;&nbsp; 1. mysql&gt; desc part_tab;<br>&nbsp;&nbsp; 2. +——-+————-+——+—–+———+——-+<br>&nbsp;&nbsp; 3. | Field | Type | Null | Key | Default | Extra |<br>&nbsp;&nbsp; 4. +——-+————-+——+—–+———+——-+<br>&nbsp;&nbsp; 5. | c1 | int(11) | YES | | NULL | |<br>&nbsp;&nbsp; 6. | c2 | varchar(30) | YES | | NULL | |<br>&nbsp;&nbsp; 7. | c3 | date | YES | | NULL | |<br>&nbsp;&nbsp; 8. +——-+————-+——+—–+———+——-+<br>&nbsp;&nbsp; 9. 3 rows in set (0.03 sec)<br>&nbsp; 10. mysql&gt; alter table part_tab drop column c2;<br>&nbsp; 11. Query OK, 8000000 rows affected (42.20 sec)<br>&nbsp; 12. Records: 8000000 Duplicates: 0 Warnings: 0<br>&nbsp; 13. mysql&gt; desc part_tab;<br>&nbsp; 14. +——-+———+——+—–+———+——-+<br>&nbsp; 15. | Field | Type | Null | Key | Default | Extra |<br>&nbsp; 16. +——-+———+——+—–+———+——-+<br>&nbsp; 17. | c1 | int(11) | YES | | NULL | |<br>&nbsp; 18. | c3 | date | YES | | NULL | |<br>&nbsp; 19. +——-+———+——+—–+———+——-+<br>&nbsp; 20. 2 rows in set (0.00 sec)<br>&nbsp; 21. mysql&gt; select count(*) from part_tab where<br>&nbsp; 22. -&gt; c3 &gt; date ‘1995-01-01′ and c3 &lt; date ‘1995-12-31′;<br>&nbsp; 23. +———-+<br>&nbsp; 24. | count(*) |<br>&nbsp; 25. +———-+<br>&nbsp; 26. | 795181 |<br>&nbsp; 27. +———-+<br>&nbsp; 28. 1 row in set (0.34 sec) <br><br>在设计上去掉了VARCHAR字段后，不止是你，俺也发现查询响应速度上获得了另一个90％的时间节省。所以大家在设计表的时候，一定要考虑，表中的字段是否真正关联，又是否在你的查询中有用？<br><br>补充说明<br><br>这么简单的文章肯定不能说全MySQL 5.1 分区机制的所有好处和要点（虽然对自己写文章水平很有信心），下面就说几个感兴趣的：<br><br>◆支持所有存储引擎(MyISAM, Archive, InnoDB, 等等)<br><br>◆ 对分区的表支持索引，包括本地索引local indexes，对其进行的是一对一的视图镜像，假设一个表有十个分区，那么其本地索引也包含十个分区。<br><br>◆关于分区的元数据Metadata的表可以在INFORMATION_SCHEMA数据库中找到，表名为PARTITIONS。<br><br>◆All SHOW 命令支持返回分区表以及元数据的索引。<br><br>◆对其操作的命令和实现的维护功能有（比对全表的操作还多）：<br><br><br><br>&nbsp;&nbsp; 1. o ADD PARTITION<br>&nbsp;&nbsp; 2. o DROP PARTITION<br>&nbsp;&nbsp; 3. o COALESCE PARTITION<br>&nbsp;&nbsp; 4. o REORGANIZE PARTITION<br>&nbsp;&nbsp; 5. o ANALYZE PARTITION<br>&nbsp;&nbsp; 6. o CHECK PARTITION<br>&nbsp;&nbsp; 7. o OPTIMIZE PARTITION<br>&nbsp;&nbsp; 8. o REBUILD PARTITION<br>&nbsp;&nbsp; 9. o REPAIR PARTITION <br><br>站在性能主导的观点上来说，MySQL 5.1的分区功能能给数据性能带来巨大的提升的同时减轻DBA的管理负担，如果分区合理的话。如果需要更多的资料可以去 http://dev.mysql.com/doc/refman/5.1/en/partitioning.html或 http://forums.mysql.com/list.php?106获得相关资料。<br><br>]]></content:encoded>
				</item>			
							<item>
					<title>PHP里模拟$_PUT</title>
					<link>http://www.phpv.net/html/1705.html</link>
					<comments>http://www.phpv.net/html/1705.html#comment</comments>
					<pubDate>Tue, 10 Nov 2009 10:30:02 +0800</pubDate>
					<dc:creator>抽烟的蚊子</dc:creator>
					<category><![CDATA[PHP技术文档]]></category>
					<guid isPermaLink="false">http://www.phpv.net/html/1705.html</guid>
					<description><![CDATA[PHP里有$_GET，$_POST，但是没有$_PUT  本文介绍使用php://input特性来模拟$_PUT]]></description>
					<content:encoded><![CDATA[PHP里有$_GET，$_POST，但是没有$_PUT，所以如果需要使用它的话，则你不得不自己模拟一下：<br><br>&nbsp;$_PUT = array();<br>if ('PUT' == $_SERVER['REQUEST_METHOD']) {<br>&nbsp;&nbsp;&nbsp;&nbsp; parse_str(file_get_contents('php://input'), $_PUT);<br>&nbsp;}<br><br>通过php://input得到的数据是raw data，所以需要用parse_str解析一下。<br><br>不过需要说明的是，当表单是enctype="multipart/form-data"类型的时候（就是上传文件那种类型），这种方法是无效的（此时 php://input为空），一旦PHP发现请求的Content-Type是multipart/form-data，就会无条件的代你处理表单数据，然后保存到$_FILES里，此时无法得到raw data，只能用一些偏门方法<br><br>以apache为例，修改httpd.conf（为了使用RequestHeader语法，请先激活header模块）：<br><br>&lt;Location "/demo.php"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp; RequestHeader set Content-Type foobar<br>&nbsp;&lt;/Location&gt;<br><br>通过重置Content-Type请求头为foobar（只要不是multipart/form-data即可），此时php://input就有数据了，不过原本应有的$_FILES数据却不存在了，所以基本上只有演示上的意义，如果想得到raw data，只能自己根据数据生成，在PEAR里有类似的实现：HTTP_Request2_MultipartBody。<br><br>浏览器一般只允许使用GET/POST方法，虽然可以通过JS来发送PUT方法，但是还得编写代码，相对而言，使用命令行下的CURL命令则显得方便很多，在开发测试时很有用，所以学习一下还是必要的：<br><br>curl -X PUT http://www.domain.com/demo.php -d "id=1" -d "title=a"<br><br>这样就会通过PUT方法发送id, title数据，测试时demo.php的代码就类似上面的php://input。 <br>]]></content:encoded>
				</item>			
							<item>
					<title>HR与程序员是怎么读你的求职简历的</title>
					<link>http://www.phpv.net/html/1704.html</link>
					<comments>http://www.phpv.net/html/1704.html#comment</comments>
					<pubDate>Tue, 10 Nov 2009 10:18:26 +0800</pubDate>
					<dc:creator>admin</dc:creator>
					<category><![CDATA[其它杂谈]]></category>
					<guid isPermaLink="false">http://www.phpv.net/html/1704.html</guid>
					<description><![CDATA[程序员是这样阅读简历的
曾经因为好玩而写过操作系统或编译器。+15
为开源软件贡献过代码。+11分
上学的时候曾经写过操作系统或编译器。+9分
在技能中，把Visual Basic列在第一的位置。-10分
简历中的缩进同时使用了空格和Tab键。-15分
]]></description>
					<content:encoded><![CDATA[<h4>人事部门是这样阅读简历的</h4><br><br>
<ul><li>（+15分）如果简历中说到了和工作职位相符的技能超过5次以上。</li><li>（+8分）如果简历中说到了和工作职位相符的技能3次到5次。</li><li>（+4分）如果简历中说到了和工作职位相符的技能1次到2次。</li><li>（+4分）Cover Letter（“求职信”或“自荐信”）提到了招聘人员。</li><li>（+2分）简历中有Cover Letter（求职信）。</li><li>（-10分）没有提到和职位描述相关的技能。</li><li>（-15分）没有受过大专教育。</li></ul>
<h4><br></h4><h4>程序员是这样阅读简历的</h4><br>
<ul><li>（+15分）曾经因为好玩而写过操作系统或编译器。</li><li>（+12分）简历被Latex编译过。</li><li>（+11分）为开源软件贡献过代码。</li><li>（+9分）上学的时候曾经写过操作系统或编译器。</li><li>（+8分）有一个BLOG分享技术知识。</li><li>（+8分）编程/机器人/工程俱乐部主席。</li><li>（+7分）编程/机器人/工程竞赛参与者。</li><li>（+7分）在Google和Microsoft实习过。</li><li>（+6分）使用动态语言（Python/Perl/Ruby）写过非试验性的程序。</li><li>（+5分）知道3种或多于3种的编程语言。</li><li>（+5分）之前的工作和目前的职位有很相似的经验。</li><li>（+4分）有过实习经验。</li><li>（+4分）自己创过业开过公司。</li><li>（+4分）有一个通过Rail, PHP或ASP.NET的个人主页。</li><li>（+3分）有一个自己域名的邮件地址。</li><li>（+3分）改过一些由动态语言（Python/Perl/Ruby）写的程序。</li><li>（+2分）有一个个人主页。</li><li>（+1分）高学历，学习成绩优秀，等。</li><li>（+0分）有奖学金。</li><li>（+0分）在快餐店工作过。</li><li>（-0.5分）Fackbook上有一张看上去喝醉了的照片。</li><li>（-1分）有博士头衔。</li><li>（-2分）有一个一般的求职信。</li><li style="color: rgb(255, 0, 0);">（-2分）在简历中说自己懂Word/Excel。</li><li>（-2分）在简历中有拼写和语法错误。</li><li>（-3分）简历的字体太小。</li><li>（-4分）所有的编程经验只是在学校中。</li><li>（-4分）只知道一门编程语言。</li><li>（-6分）简历有三页以上。</li><li>（-6分）简历中有一些无关的东西。</li><li>（-7分）得到过一些课程的认证。</li><li>（-8分）相关专业课程很低的成绩。</li><li>（-10分）在技能中，把Visual Basic列在第一的位置。</li><li>（-12分）在Facebook中，有过光膀子的照片。</li><li style="color: rgb(255, 0, 0);">（-15分）简历中的缩进同时使用了空格和Tab键。</li></ul>
<p><br></p><p>我个人觉得其中的很多东西真是说出了程序员的那种特性。</p><p>配图<br>------------------------------------------------<br></p><p>下面这个图片来源国外，是一个关于程序员面试时的简历，被人事部门和程序员本身评审的角度不同的图片。当然，这是一个从国外面试的视角制作的图片，不过，可以看出，其中很多东西都是和国内是相同的。让我们通过这个图片也来了解一下自身吧。
</p><p align="center"><a href="http://coolshell.cn/wp-content/uploads/2009/11/resume_comic.png" target="_blank"><img title="程序员怎样阅读简历" src="http://www.phpv.net/uploadfile/month_200911/local_xKbmGM1lkg.png" alt="程序员怎样阅读简历（点击看大图）" height="1024" width="552"></a></p>



]]></content:encoded>
				</item>			
							<item>
					<title>谈PHP 闭包特性在实际应用中的问题</title>
					<link>http://www.phpv.net/html/1703.html</link>
					<comments>http://www.phpv.net/html/1703.html#comment</comments>
					<pubDate>Tue, 13 Oct 2009 10:15:52 +0800</pubDate>
					<dc:creator>抽烟的蚊子</dc:creator>
					<category><![CDATA[PHP5研究[新]]]></category>
					<guid isPermaLink="false">http://www.phpv.net/html/1703.html</guid>
					<description><![CDATA[PHP5.3 新版本跟随了很多新特性， 其中比较惹眼的特性之一就是支持了闭包。那么以后，我们也可以和那帮写 Ruby、Javascript 等等“高科技语言”的家伙们一样，写出非常酷的代码吗？呃，其实大部分情况下是可以的，而有些方面还是令人非常的困扰]]></description>
					<content:encoded><![CDATA[<p>原文链接： <a href="http://justafewlines.com/2009/10/whats-wrong-with-php-closures/" title="http://justafewlines.com/2009/10/whats-wrong-with-php-closures/">http://justafewlines.com/2009/10/whats-wrong-with-php-closures/</a></p>

<p><a href="http://php.net/releases/5_3_0.php" title="http://php.net/releases/5_3_0.php">PHP5.3 新版本跟随了很多新特性</a>， 其中比较惹眼的特性之一就是支持了闭包。那么以后，我们也可以和那帮写 Ruby、Javascript 等等“高科技语言”的家伙们一样，写出非常酷的代码吗？呃，其实大部分情况下是可以的，而有些方面还是令人非常的困扰，下面慢慢道来。</p>

<p>很多语言的都提供了非常优雅和漂亮的操作数组的方法。在下面的例子中，会使用 PHP5.3 以及其他语言提供的闭包功能，用于展示如何“客观的”操作迭代数组。</p>

<p>译注：原文作者比较火星，我不了解 Groovy 以及 Scala 语言，所以这里我加上 Javascript 的实现。</p>

<p>在开始之前先说明下，本例子仅仅是阐明观点，并没有考虑性能等其他方面的因素。</p>

<h2>“货比三家”</h2><p>用个简单的例子开始，有下面个数组：</p>

<pre>$nums = array(10, 20, 30, 40);</pre><p>需要找出数组中大于 15 的项。那么，不考虑闭包的情况下，我们或许会这样写：</p>

<pre>$res = array();<br>foreach ($nums as $n) {<br>    if ($n &gt; 15) {<br>        $res[] = $n;<br>    }<br>}</pre><p>如果语言本身有闭包支持的，那么或许会这样写（Groovy 语言）</p>

<pre>def res = nums.findAll { it &gt; 15 }</pre><p>或者使用 Scala 语言</p>

<pre>val res = nums filter (_ &gt; 15)</pre><p>译注：Javascript 1.6 的话会是如下</p>

<pre>var res = nums.filter(function(c){return c &gt; 15});</pre><p>因为循环操作已被抽象起来，所以可以看到 Groovy 、Scala （以及 Javascript） 都很漂亮得用一行就可以搞定。</p>

<p>当然，如果使用 PHP5.3 的闭包，也可以做到</p>

<pre>$res = array_filter($nums, function($v) { return $v &gt; 15; });</pre><p>PHP 在这方面使用了比 Scala 更多的字符，但对比先前的例子，它更简短并且能更好得阅读。</p>

<p>顺便说下，上面的 PHP 代码实际上是使用了 Lambda 解析式，并不是个真正的闭包，这个 并不是我们目前关注的重点。详细阐述 PHP 闭包以及 Lambda 解析式的资料，可以<a href="http://wiki.php.net/rfc/closures" title="http://wiki.php.net/rfc/closures">参考这里</a>。</p>

<p>目前看来感觉都还不错，那么我们再的题目增加点难度：找到所有大于 15 的项， 然后乘以 2 再加上作用域中的的某个变量值以后再返回。</p>

<p>Groovy 的实现：</p>

<pre>def x = 1<br>def res = nums .findAll { it &gt; 15 } .collect { it * 2 + x }</pre><p>Scala 的实现：</p>

<pre>val x = 1<br>val res = nums filter (_ &gt; 15) map (_ * 2 + x)</pre><p>译注，Javascript 的实现：</p>

<pre>var i = 1;<br>var res = nums.filter(function(c){return c &gt; 15}).map(function(c){return c * 2 + i});</pre><p>以及 PHP：</p>

<pre>$x = 1;<br>$res = array_map(<br>    function($v) use ($x) { return $v * 2 + $x; },<br>    array_filter(<br>        $nums,<br>        function($v) { return $v &gt; 15; })<br>);</pre><p>光从代码量方面，现在看起来 PHP 与其他语言有出入了。先抛开代码字面上本身 的审美不谈，上面的 PHP 代码还有个额外的问题。</p>

<p>例如，如果需要使用数组的键而非值作比较，怎么办？是的，上面的代码就办不到了。同时，从语法角度上说，上面的代码非常难以阅读。</p>

<p>返璞归真，这时还是得返回老土的思路去解决问题：</p>

<pre>$x = 1;<br>$res = array();<br>foreach ($nums as $n) {<br>    if ($n &gt; 15) {<br>        $res[] = $n * 2 + $x;<br>    }<br>}</pre><p>呼，这样看起来又很清楚了。但这个时候你或许又会迷惑了：“那还瞎折腾啥，这不就是个数组操作吗？”。</p>

<p>是的，好戏还在后头。这个时候该让 PHP 的某些高级特性出场，来搞定这看似有自残倾向 的“无聊问题”。</p>

<h2>ArrayObject – 对数组的封装</h2><p>PHP 有个称作 <a href="http://www.gracecode.com/archives/2965/" title="http://www.gracecode.com/archives/2965/">SPL 的标准库</a>，其中包含了个叫做 <a href="http://php.net/manual/en/class.arrayobject.php" title="http://php.net/manual/en/class.arrayobject.php">ArrayObject</a> 的类，它能提供“像数组一 样操作类”的功能，例如</p>

<pre>$res = new ArrayObject(array(10, 20, 30, 40));<br>foreach ($res as $v) {<br>    echo "$vn";<br>}</pre><p>ArrayObject 是个内置的类，所以你可以像其他类类操作一样封装它。</p>

<h2>Arr - 包上糖衣</h2><p>既然我们已经有了 ArrayObject 以及闭包这些特性，我们就可以开始尝试封装它：</p>

<pre>class Arr extends ArrayObject<br>{<br>    static function make($array)<br>    {<br>        return new self($array);<br>    }<br><br>    function map($func)<br>    {<br>        $res = new self();<br>        foreach ($this as $k =&gt; $v) {<br>            $res[$k] = $func($k, $v);<br>        }<br>        return $res;<br>    }<br><br>    function filter($func)<br>    {<br>        $res = new self();<br>        foreach ($this as $k =&gt; $v) {<br>            if ($func($k, $v)) {<br>                $res[$k] = $v;<br>            }<br>        }<br>        return $res;<br>    }<br>}</pre><p>好了，万事俱备。下面重写的 PHP 代码就可以解决上面提到的问题，并且看起来语法上“差 不多”了：</p>

<pre>$res = Arr::make($nums)<br>    -&gt;filter(function($k, $v) { return $v &gt; 15; })<br>    -&gt;map(function($k, $v) { return $v * 2; });</pre><p>上面的代码与传统方式有何不同呢？首先，它们可以递归并形成作用链式的调用，因此可以 添加更多的类似操作。</p>

<p>同时，可以通过回调的两个参数分别操作数组的键以及值其项 - $k 对应键以及 $v 对应值 。这使得我们可以在闭包中使用键值，这在传统的 PHP 函数 array_fliter 中是无法实现的。</p>

<p>另外个带来的额外好处就是更加一致 API 调用。使用传统的 PHP 函数操作，它们有可能第一个参数是个闭包，或者是个数组，抑或是多个数组…总之谁知道呢？</p>

<p><a href="http://justafewlines.com/wp-content/uploads/2009/10/closures-arr-example.zip" title="http://justafewlines.com/wp-content/uploads/2009/10/closures-arr-example.zip">这里是 Arr 类的完整源代码</a>，还包含了其他有用的函数（类似 reduce 以及 walk），其实它 们的实现其实方式和代码类似。</p>

<h2>博弈</h2><p>这个问题其实很难回答 - 这需要根据代码的上下文以及程序员自身等众多因素决定。其实 ，当我第一眼看见 PHP 的闭包实现时，我感觉似乎回到了那很久以前的 Java 时期，当时 我在开始使用<a href="http://www.roseindia.net/javatutorials/anonymous_innerclassestutorial.shtml" title="http://www.roseindia.net/javatutorials/anonymous_innerclassestutorial.shtml">匿名内置类（anonymous inner classes）</a>来实现闭包。当然，这虽然可以做到， 但看起来实在是些画蛇添足。PHP 闭包本身是没错，只是它的实现以及语法让我感到非常的困惑。</p>

<p>其他具有闭包特性的语言，它们可以非常方便的调用闭包并同时具有优雅的语法。在上面的例子 中，在 Scala 中使用传统的循环也可以工作，但你会这样写吗？而从另个方面，那么有人 说上面这个题目使用 PHP 的闭包也可以实现，但一般情况下你会这样写吗？</p>

<p>可以确定，PHP 闭包在些情况下可以成为锐利的军刀（例如延时执行以及资源调用方面）， 但在传统的迭代以及数组操作面前就显得有些为难。不要气馁不管怎么样， 返璞归真编写具有兼容性的、清爽的代码以及 API 是最重要的。</p>

<h2>结束语</h2><p>像所有后来加上的语法特性一样（记得当年 Java 的 Generics 特性不？以及前几年的 PHP OOP
特性），它们都需要时间磨合以及最终稳定下来。随着 PHP5.3 甚至将来的 PHP6
逐渐普及，越来越多的技巧和特性相信在不远的将来逐渐的被聪明的程序员挖掘出来。</p>

<p>回到最初文章开头那个题目，对比</p>

<pre>$res = Arr::make($nums)<br>    -&gt;filter(function($k, $v) { return $v &gt; 15; })<br>    -&gt;map(function($k, $v) { return $v * 2; });</pre><p>以及</p>

<pre>val res = nums filter (_ &gt; 15) map (_ * 2)</pre><p>两者之间的区别。归根结底它们仅是语法而已，本质上都是殊途同归解决了同个问题。程序 语言的应用特性不同，自然孰优孰劣也就无从比较。</p>

<p>最后，<a href="http://justafewlines.com/wp-content/uploads/2009/10/closures-arr-example.zip" title="http://justafewlines.com/wp-content/uploads/2009/10/closures-arr-example.zip">这里有此篇文章的代码示例</a>， 相信可以找到更多如何使用 PHP 进行函数式迭代（当然不仅仅是这些）的心得。</p>

<p><tt>-- Split --</tt></p>

<h2>不靠谱之博主心得</h2><p>坦白讲，虽然在 PHP5.0 之前就了解过提出的新增闭包等功能，但在看到 PHP5.3 提供的闭 包以及 Lambda 功能后，与原本心理期待的还是有些出入。</p>

<p>甚至相对于熟悉的 JavaScript，PHP 的闭包在我看来，像是“别的语言都有了，所以我也要有” 的这种心态下的产物。</p>

<p>但正如上文中所言，相比 JavaScript 等其他动态语言，PHP 出于自身的应用以及实现的哲学 出发，与其他开发语言不尽相同。</p>

<p>因此在某些特性的调用方式、实现方法也会不一样，这难免会让熟悉另外具有类似功能的语言 的人感到的不适应。</p>

<p>从 PHP5.3 推出至今，还不到半年的时间，相比 JavaScript 等这些早已具有闭包等特性的 动态语言相比，自然是显得非常稚嫩。</p>

<p>同时，广大的开发者对于 PHP5.3 提供的包括闭包在内的新特性还在持观望态度。PHP 的闭包特性目前还是存在于实验室中，其应用于实际开发如要突破的不仅仅是语言特性 ，还要经过效率、安全性等方面的考验。</p>

<p>但相信，如原文作者所言，随着 PHP 版本的推进，PHP 的闭包应用场合会越来越频繁。像 当年 PHP4 转换到 PHP5 一样，对语言新特性的适应，其实是种痛并快乐着的过程。</p>

]]></content:encoded>
				</item>			
							<item>
					<title>JavaScript可否多线程? 深入理解JavaScript定时机制</title>
					<link>http://www.phpv.net/html/1700.html</link>
					<comments>http://www.phpv.net/html/1700.html#comment</comments>
					<pubDate>Sun, 27 Sep 2009 11:41:00 +0800</pubDate>
					<dc:creator>admin</dc:creator>
					<category><![CDATA[前端交互]]></category>
					<guid isPermaLink="false">http://www.phpv.net/html/1700.html</guid>
					<description><![CDATA[浏览器中的JavaScript引擎是基于事件驱动的,这里的事件可看作是浏览器派给它的各种任务,这些任务可以源自 JavaScript引擎当前执行的代码块,如调用setTimeout添加一个任务,也可来自浏览器内核的其它线程,如界面元素鼠标点击事件,定时触发器时间到达通知,异步请求状态变更通知等.从代码角度看来任务实体就是各种回调函数,JavaScript引擎一直等待着任务队列中任务的到来.由于单线程关系,这些任务得进行排队,一个接着一个被引擎处理.]]></description>
					<content:encoded><![CDATA[<p>JavaScript的setTimeout与setInterval是两个很容易欺骗别人感情的方法,因为我们开始常常以为调用了就会按既定的方式执行, 我想不少人都深有同感, 例如</p>
<blockquote><p>
setTimeout( function(){ alert(’你好!’); } , 0);<br>
setInterval( callbackFunction , 100);
</p></blockquote>
<p>认为setTimeout中的问候方法会立即被执行,因为这并不是凭空而说,而是JavaScript API文档明确定义第二个参数意义为隔多少毫秒后,回调方法就会被执行. 这里设成0毫秒,理所当然就立即被执行了.<br>
同理对setInterval的callbackFunction方法每间隔100毫秒就立即被执行深信不疑!</p>
<p>但随着JavaScript应用开发经验不断的增加和丰富,有一天你发现了一段怪异的代码而百思不得其解:</p>
<blockquote><p>
 div.onclick = function(){<br>
    setTimeout( function(){document.getElementById(’inputField’).focus();}, 0);<br>
 };
</p></blockquote>
<p>既然是0毫秒后执行,那么还用setTimeout干什么, 此刻, 坚定的信念已开始动摇.<br>
<span id="more-341"></span><br>
直到最后某一天 , 你不小心写了一段糟糕的代码:</p>
<blockquote><p>
setTimeout( function(){ while(true){} } , 100);<br>
setTimeout( function(){ alert(’你好!’); } , 200);<br>
setInterval( callbackFunction , 200);
</p></blockquote>
<p>第一行代码进入了死循环,但不久你就会发现,第二,第三行并不是预料中的事情,alert问候未见出现,callbacKFunction也杳无音讯!</p>
<p>这时你彻底迷惘了,这种情景是难以接受的,因为改变长久以来既定的认知去接受新思想的过程是痛苦的,但情事实摆在眼前,对JavaScript真理的探求并不会因为痛苦而停止,下面让我们来展开JavaScript线程和定时器探索之旅!</p>
<p><strong>拔开云雾见月明</strong></p>
<p>出现上面所有误区的最主要一个原因是:潜意识中认为,JavaScript引擎有多个线程在执行,JavaScript的定时器回调函数是异步执行的.</p>
<p>而事实上的,JavaScript使用了障眼法,在多数时候骗过了我们的眼睛,这里背光得澄清一个事实:</p>
<blockquote><p>
<strong>JavaScript引擎是单线程运行的,浏览器无论在什么时候都只且只有一个线程在运行JavaScript程序.</strong>
</p></blockquote>
<p>JavaScript引擎用单线程运行也是有意义的,单线程不必理会线程同步这些复杂的问题,问题得到简化.</p>
<p>那么单线程的JavaScript引擎是怎么配合浏览器内核处理这些定时器和响应浏览器事件的呢?<br>
下面结合浏览器内核处理方式简单说明.</p>
<p>浏览器内核实现允许多个线程异步执行,这些线程在内核制控下相互配合以保持同步.假如某一浏览器内核的实现至少有三个常驻线
程:javascript引擎线程,界面渲染线程,浏览器事件触发线程,除些以外,也有一些执行完就终止的线程,如Http请求线程,这些异步线程都会产
生不同的异步事件,下面通过一个图来阐明单线程的JavaScript引擎与另外那些线程是怎样互动通信的.虽然每个浏览器内核实现细节不同,但这其中的
调用原理都是大同小异.</p>
<p><a href="http://www.phpv.net/uploadfile/month_200909/local_iq9hPSQMfQ.jpg" target="_blank"><img alt="" src="http://www.phpv.net/uploadfile/month_200909/local_9CBIg5d80M.jpg" align="" border="0px"><br></a></p>
<p>由图可看出,浏览器中的JavaScript引擎是基于事件驱动的,这里的事件可看作是浏览器派给它的各种任务,这些任务可以源自
JavaScript引擎当前执行的代码块,如调用setTimeout添加一个任务,也可来自浏览器内核的其它线程,如界面元素鼠标点击事件,定时触发
器时间到达通知,异步请求状态变更通知等.从代码角度看来任务实体就是各种回调函数,JavaScript引擎一直等待着任务队列中任务的到来.由于单线
程关系,这些任务得进行排队,一个接着一个被引擎处理.</p>
<p>上图t1-t2..tn表示不同的时间点,tn下面对应的小方块代表该时间点的任务,假设现在是t1时刻,引擎运行在t1对应的任务方块代码内,在这个时间点内,我们来描述一下浏览器内核其它线程的状态.</p>
<p><strong>t1时刻:</strong></p>
<p>GUI渲染线程:</p>
<p>该线程负责渲染浏览器界面HTML元素,当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行.本文虽然重
点解释JavaScript定时机制,但这时有必要说说渲染线程,因为该线程与JavaScript引擎线程是互斥的,这容易理解,因为
JavaScript脚本是可操纵DOM元素,在修改这些元素属性同时渲染界面,那么渲染线程前后获得的元素数据就可能不一致了.</p>
<blockquote><p>
<strong>在JavaScript引擎运行脚本期间,浏览器渲染线程都是处于挂起状态的,也就是说被”冻结”了.</strong>
</p></blockquote>
<p>所以,在脚本中执行对界面进行更新操作,如添加结点,删除结点或改变结点的外观等更新并不会立即体现出来,这些操作将保存在一个队列中,待JavaScript引擎空闲时才有机会渲染出来.</p>
<p>GUI事件触发线程:</p>
<p>JavaScript脚本的执行不影响html元素事件的触发,在t1时间段内,首先是用户点击了一个鼠标键,点击被浏览器事件触发线程捕捉后形成
一个鼠标点击事件,由图可知,对于JavaScript引擎线程来说,这事件是由其它线程异步传到任务队列尾的,由于引擎正在处理t1时的任务,这个鼠标
点击事件正在等待处理.</p>
<p>定时触发线程:</p>
<p>注意这里的浏览器模型定时计数器并不是由JavaScript引擎计数的,因为JavaScript引擎是单线程的,如果处于阻塞线程状态就计不了时,它必须依赖外部来计时并触发定时,所以队列中的定时事件也是异步事件.</p>
<p>由图可知,在这t1的时间段内,继鼠标点击事件触发后,先前已设置的setTimeout定时也到达了,此刻对JavaScript引擎来说,定时触发线程产生了一个异步定时事件并放到任务队列中, 该事件被排到点击事件回调之后,等待处理.<br>
同理, 还是在t1时间段内,接下来某个setInterval定时器也被添加了,由于是间隔定时,在t1段内连续被触发了两次,这两个事件被排到队尾等待处理.</p>
<p>可见,假如时间段t1非常长,远大于setInterval的定时间隔,那么定时触发线程就会源源不断的产生异步定时事件并放到任务队列尾而不管它
们是否已被处理,但一旦t1和最先的定时事件前面的任务已处理完,这些排列中的定时事件就依次不间断的被执行,这是因为,对于JavaScript引擎来
说,在处理队列中的各任务处理方式都是一样的,只是处理的次序不同而已.</p>
<p>t1过后,也就是说当前处理的任务已返回,JavaScript引擎会检查任务队列,发现当前队列非空,就取出t2下面对应的任务执行,其它时间依此类推,由此看来:</p>
<blockquote><p>
<strong>如果队列非空,引擎就从队列头取出一个任务,直到该任务处理完,即返回后引擎接着运行下一个任务,在任务没返回前队列中的其它任务是没法被执行的.</strong>
</p></blockquote>
<p>相信您现在已经很清楚JavaScript是否可多线程,也了解理解JavaScript定时器运行机制了,下面我们来对一些案例进行分析:</p>
<p><strong>案例1:setTimeout与setInterval</strong></p>
<pre>setTimeout(function(){<br>   /* 代码块... */<br>   setTimeout(arguments.callee, 10);<br>}, 10);<br><br>setInterval(function(){<br>   /*代码块... */<br> }, 10);<br></pre>
<p>这两段代码看一起效果一样,其实非也,第一段中回调函数内的setTimeout是JavaScript引擎执行后再设置新的setTimeout
定时, 假定上一个回调处理完到下一个回调开始处理为一个时间间隔,理论两个setTimeout回调执行时间间隔&gt;=10ms
.第二段自setInterval设置定时后,定时触发线程就会源源不断的每隔十秒产生异步定时事件并放到任务队列尾,理论上两个setInterval
回调执行时间间隔&lt;=10.</p>
<p><strong>案例2:ajax异步请求是否真的异步?</strong></p>
<p>很多同学朋友搞不清楚,既然说JavaScript是单线程运行的,那么XMLHttpRequest在连接后是否真的异步?<br>
其实请求确实是异步的,不过这请求是由浏览器新开一个线程请求(参见上图),当请求的状态变更时,如果先前已设置回调,这异步线程就产生状态变更事件放到
JavaScript引擎的处理队列中等待处理,当任务被处理时,JavaScript引擎始终是单线程运行回调函数,具体点即还是单线程运行
onreadystatechange所设置的函数.</p>

]]></content:encoded>
				</item>			
					
	</channel>
</rss>
