<?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>Terrysco&#039;s Blog &#187; web</title>
	<atom:link href="http://www.terrysco.com/node/tag/web/feed" rel="self" type="application/rss+xml" />
	<link>http://www.terrysco.com</link>
	<description>仅关注于互联网行业， Linux平台开发。</description>
	<lastBuildDate>Sat, 05 Nov 2011 21:24:06 +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>[转] 大型网站架构演变和知识体系</title>
		<link>http://www.terrysco.com/node/web-arch-knowledge.html</link>
		<comments>http://www.terrysco.com/node/web-arch-knowledge.html#comments</comments>
		<pubDate>Mon, 13 Oct 2008 05:05:47 +0000</pubDate>
		<dc:creator>terrysco</dc:creator>
				<category><![CDATA[Web Architecture]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.terrysco.com/?p=257</guid>
		<description><![CDATA[本文来源：http://www.blogjava.net/BlueDavy/archive/2008/09/03/226749.html 之前也有一些介绍大型网站架构演变的文章，例如LiveJournal的、ebay的，都是非常值得参考的，不过感觉他们讲的更多的是每次演变的结果，而没有很详细的讲为什么需要做这样的演变，再加上近来感觉有不少同学都很难明白为什么一个网站需要那么复杂的技术，于是有了写这篇文章的想法，在这篇文章中 将阐述一个普通的网站发展成大型网站过程中的一种较为典型的架构演变历程和所需掌握的知识体系，希望能给想从事互联网行业的同学一点初步的概念，:-)，文中的不对之处也请各位多给点建议，让本文真正起到抛砖引玉的效果。 架构演变第一步：物理分离webserver和数据库 最开始，由于某些想法，于是在互联网上搭建了一个网站，这个时候甚至有可能主机都是租借的，但由于这篇文章我们只关注架构的演变历程，因此就假设这个时候 已 经是托管了一台主机，并且有一定的带宽了，这个时候由于网站具备了一定的特色，吸引了部分人访问，逐渐你发现系统的压力越来越高，响应速度越来越慢，而这 个时候比较明显的是数据库和应用互相影响，应用出问题了，数据库也很容易出现问题，而数据库出问题的时候，应用也容易出问题，于是进入了第一步演变阶段： 将应用和数据库从物理上分离，变成了两台机器，这个时候技术上没有什么新的要求，但你发现确实起到效果了，系统又恢复到以前的响应速度了，并且支撑住了更 高的流量，并且不会因为数据库和应用形成互相的影响。 看看这一步完成后系统的图示： 这一步涉及到了这些知识体系： 这一步架构演变对技术上的知识体系基本没有要求。 架构演变第二步：增加页面缓存 好景不长，随着访问的人越来越多，你发现响应速度又开始变慢了，查找原因，发现是访问数据库的操作太多，导致数据连接竞争激烈，所以响应变慢，但数据库连 接又不能开太多，否则数据库机器压力会很高，因此考虑采用缓存机制来减少数据库连接资源的竞争和对数据库读的压力，这个时候首先也许会选择采用squid 等类似的机制来将系统中相对静态的页面（例如一两天才会有更新的页面）进行缓存（当然，也可以采用将页面静态化的方案），这样程序上可以不做修改，就能够 很好的减少对webserver的压力以及减少数据库连接资源的竞争，OK，于是开始采用squid来做相对静态的页面的缓存。 看看这一步完成后系统的图示： 这一步涉及到了这些知识体系： 前端页面缓存技术，例如squid，如想用好的话还得深入掌握下squid的实现方式以及缓存的失效算法等。 架构演变第三步：增加页面片段缓存 增加了squid做缓存后，整体系统的速度确实是提升了，webserver的压力也开始下降了，但随着访问量的增加，发现系统又开始变的有些慢了，在尝 到了squid之类的动态缓存带来的好处后，开始想能不能让现在那些动态页面里相对静态的部分也缓存起来呢，因此考虑采用类似ESI之类的页面片段缓存策略，OK，于是开始采用ESI来做动态页面中相对静态的片段部分的缓存。 看看这一步完成后系统的图示： 这一步涉及到了这些知识体系： 页面片段缓存技术，例如ESI等，想用好的话同样需要掌握ESI的实现方式等； 架构演变第四步：数据缓存 在采用ESI之类的技术再次提高了系统的缓存效果后，系统的压力确实进一步降低了，但同样，随着访问量的增加，系统还是开始变慢，经过查找，可能会发现系 统中存在一些重复获取数据信息的地方，像获取用户信息等，这个时候开始考虑是不是可以将这些数据信息也缓存起来呢，于是将这些数据缓存到本地内存，改变完毕后，完全符合预期，系统的响应速度又恢复了，数据库的压力也再度降低了不少。 看看这一步完成后系统的图示： 这一步涉及到了这些知识体系： 缓存技术，包括像Map数据结构、缓存算法、所选用的框架本身的实现机制等。 架构演变第五步： 增加webserver 好景不长，发现随着系统访问量的再度增加，webserver机器的压力在高峰期会上升到比较高，这个时候开始考虑增加一台webserver，这也是为了同时解决可用性的问题，避免单台的webserver down机的话就没法使用了，在做了这些考虑后，决定增加一台webserver，增加一台webserver时，会碰到一些问题，典型的有： 1、如何让访问分配到这两台机器上，这个时候通常会考虑的方案是Apache自带的负载均衡方案，或LVS这类的软件负载均衡方案； 2、如何保持状态信息的同步，例如用户session等，这个时候会考虑的方案有写入数据库、写入存储、cookie或同步session信息等机制等； 3、如何保持数据缓存信息的同步，例如之前缓存的用户数据等，这个时候通常会考虑的机制有缓存同步或分布式缓存； 4、如何让上传文件这些类似的功能继续正常，这个时候通常会考虑的机制是使用共享文件系统或存储等； 在解决了这些问题后，终于是把webserver增加为了两台，系统终于是又恢复到了以往的速度。 看看这一步完成后系统的图示： 这一步涉及到了这些知识体系： 负载均衡技术（包括但不限于硬件负载均衡、软件负载均衡、负载算法、linux转发协议、所选用的技术的实现细节等）、主备技术（包括但不限于ARP欺骗、linux heart-beat等）、状态信息或缓存同步技术（包括但不限于Cookie技术、UDP协议、状态信息广播、所选用的缓存同步技术的实现细节等）、共享文件技术（包括但不限于NFS等）、存储技术（包括但不限于存储设备等）。 架构演变第六步：分库 享受了一段时间的系统访问量高速增长的幸福后，发现系统又开始变慢了，这次又是什么状况呢，经过查找，发现数据库写入、更新的这些操作的部分数据库连接的 资 源竞争非常激烈，导致了系统变慢，这下怎么办呢，此时可选的方案有数据库集群和分库策略，集群方面像有些数据库支持的并不是很好，因此分库会成为比较普遍 的策略，分库也就意味着要对原有程序进行修改，一通修改实现分库后，不错，目标达到了，系统恢复甚至速度比以前还快了。 看看这一步完成后系统的图示： 这一步涉及到了这些知识体系： 这一步更多的是需要从业务上做合理的划分，以实现分库，具体技术细节上没有其他的要求； 但同时随着数据量的增大和分库的进行，在数据库的设计、调优以及维护上需要做的更好，因此对这些方面的技术还是提出了很高的要求的。 [...]]]></description>
			<content:encoded><![CDATA[<p>本文来源：<a href="http://www.blogjava.net/BlueDavy/archive/2008/09/03/226749.html">http://www.blogjava.net/BlueDavy/archive/2008/09/03/226749.html</a></p>
<p><span style="font-family: 宋体;">之前也有一些介绍大型网站架构演变的文章，例如</span>LiveJournal<span style="font-family: 宋体;">的、</span>ebay<span style="font-family: 宋体;">的，都是非常值得参考的，不过感觉他们讲的更多的是每次演变的结果，而没有很详细的讲为什么需要做这样的演变，再加上近来感觉有不少同学都很难明白为什么一个网站需要那么复杂的技术，于是有了写这篇文章的想法，在这篇文章中</span> <span style="font-family: 宋体;">将阐述一个普通的网站发展成大型网站过程中的一种较为典型的架构演变历程和所需掌握的知识体系，希望能给想从事互联网行业的同学一点初步的概念，:-)</span><span style="font-family: 宋体;">，文中的不对之处也请各位多给点建议，让本文真正起到抛砖引玉的效果。</span></p>
<p><strong><span style="font-family: 宋体;"><span style="font-size: 14pt;"><span style="font-family: 宋体;">架构演变第一步：物理分离</span><span onclick="tagshow(event)">web</span>server<span style="font-family: 宋体;">和数据库</span></span></span></strong><br />
<strong><span style="font-family: 宋体;"><span style="font-size: 14pt;"><br />
</span></span></strong><br />
<span style="font-family: 宋体;">最开始，由于某些想法，于是在互联网上搭建了一个网站，这个时候甚至有可能主机都是租借的，但由于这篇文章我们只关注架构的演变历程，因此就假设这个时候</span> <span style="font-family: 宋体;">已 经是托管了一台主机，并且有一定的带宽了，这个时候由于网站具备了一定的特色，吸引了部分人访问，逐渐你发现系统的压力越来越高，响应速度越来越慢，而这 个时候比较明显的是数据库和应用互相影响，应用出问题了，数据库也很容易出现问题，而数据库出问题的时候，应用也容易出问题，于是进入了第一步演变阶段： 将应用和数据库从物理上分离，变成了两台机器，这个时候技术上没有什么新的要求，但你发现确实起到效果了，系统又恢复到以前的响应速度了，并且支撑住了更 高的流量，并且不会因为数据库和应用形成互相的影响。</span><br />
<span style="font-family: 宋体;">看看这一步完成后系统的图示：</span><br />
<img src="http://www.blogjava.net/images/blogjava_net/bluedavy/arch/1.PNG" border="0" alt="" width="195" height="99" /></p>
<p><span style="font-family: 宋体;">这一步涉及到了这些知识体系：</span><br />
<span style="font-family: 宋体;">这一步架构演变对技术上的知识体系基本没有要求。</span></p>
<p><strong><span style="font-family: 宋体;"><span style="font-size: 14pt;">架构演变第二步：增加页面缓存<br />
</span></span></strong><br />
<span style="font-family: 宋体;">好景不长，随着访问的人越来越多，你发现响应速度又开始变慢了，查找原因，发现是访问数据库的操作太多，导致数据连接竞争激烈，所以响应变慢，但数据库连</span> <span style="font-family: 宋体;">接又不能开太多，否则数据库机器压力会很高，因此考虑采用缓存机制来减少数据库连接资源的竞争和对数据库读的压力，这个时候首先也许会选择采用</span>squid <span style="font-family: 宋体;">等类似的机制来将系统中相对静态的页面（例如一两天才会有更新的页面）进行缓存（当然，也可以采用将页面静态化的方案），这样程序上可以不做修改，就能够</span> <span style="font-family: 宋体;">很好的减少对</span>webserver<span style="font-family: 宋体;">的压力以及减少数据库连接资源的竞争，</span>OK<span style="font-family: 宋体;">，于是开始采用</span>squid<span style="font-family: 宋体;">来做相对静态的页面的缓存。</span><br />
<span style="font-family: 宋体;">看看这一步完成后系统的图示：</span><br />
<img src="http://www.blogjava.net/images/blogjava_net/bluedavy/arch/2.PNG" border="0" alt="" width="195" height="156" /></p>
<p><span style="font-family: 宋体;">这一步涉及到了这些知识体系：</span><br />
<span style="font-family: 宋体;">前端页面缓存技术，例如</span>squid<span style="font-family: 宋体;">，如想用好的话还得深入掌握下</span>squid<span style="font-family: 宋体;">的实现方式以及缓存的失效算法等。</span></p>
<p><strong><span style="font-family: 宋体;"><span style="font-size: 14pt;">架构演变第三步：增加页面片段缓存<br />
</span></span></strong><br />
<span style="font-family: 宋体;">增加了</span>squid<span style="font-family: 宋体;">做缓存后，整体系统的速度确实是提升了，</span>webserver<span style="font-family: 宋体;">的压力也开始下降了，但随着<span onclick="tagshow(event)">访问量</span>的增加，发现系统又开始变的有些慢了，在尝</span> <span style="font-family: 宋体;">到了</span>squid<span style="font-family: 宋体;">之类的动态缓存带来的好处后，开始想能不能让现在那些动态页面里相对静态的部分也缓存起来呢，因此考虑采用类似</span>ESI<span style="font-family: 宋体;">之类的页面片段缓存策略，</span>OK<span style="font-family: 宋体;">，于是开始采用</span>ESI<span style="font-family: 宋体;">来做动态页面中相对静态的片段部分的缓存。</span><br />
<span style="font-family: 宋体;">看看这一步完成后系统的图示：</span><br />
<img src="http://www.blogjava.net/images/blogjava_net/bluedavy/arch/3.PNG" border="0" alt="" width="337" height="235" /></p>
<p><span style="font-family: 宋体;">这一步涉及到了这些知识体系：</span><br />
<span style="font-family: 宋体;">页面片段缓存技术，例如</span>ESI<span style="font-family: 宋体;">等，想用好的话同样需要掌握</span>ESI<span style="font-family: 宋体;">的实现方式等；</span></p>
<p><strong><span style="font-family: 宋体;"><span style="font-size: 14pt;">架构演变第四步：数据缓存<br />
</span></span></strong><br />
<span style="font-family: 宋体;">在采用</span>ESI<span style="font-family: 宋体;">之类的技术再次提高了系统的缓存效果后，系统的压力确实进一步降低了，但同样，随着访问量的增加，系统还是开始变慢，经过查找，可能会发现系</span> <span style="font-family: 宋体;">统中存在一些重复获取数据信息的地方，像获取用户信息等，这个时候开始考虑是不是可以将这些数据信息也缓存起来呢，于是将这些数据缓存到本地内存，改变完毕后，完全符合预期，系统的响应速度又恢复了，数据库的压力也再度降低了不少。</span><br />
<span style="font-family: 宋体;">看看这一步完成后系统的图示：</span><br />
<img src="http://www.blogjava.net/images/blogjava_net/bluedavy/arch/4.PNG" border="0" alt="" width="341" height="258" /></p>
<p><span style="font-family: 宋体;">这一步涉及到了这些知识体系：</span><br />
<span style="font-family: 宋体;">缓存技术，包括像</span>Map<span style="font-family: 宋体;">数据结构、缓存算法、所选用的框架本身的实现机制等。</span></p>
<p><strong><span style="font-family: 宋体;"><span style="font-size: 14pt;"><span style="font-family: 宋体;">架构演变第五步：</span> <span style="font-family: 宋体;">增加</span>webserver<br />
</span></span></strong><br />
<span style="font-family: 宋体;">好景不长，发现随着系统访问量的再度增加，</span>webserver<span style="font-family: 宋体;">机器的压力在高峰期会上升到比较高，这个时候开始考虑增加一台</span>webserver<span style="font-family: 宋体;">，这也是为了同时解决可用性的问题，避免单台的</span>webserver down<span style="font-family: 宋体;">机的话就没法使用了，在做了这些考虑后，决定增加一台</span>webserver<span style="font-family: 宋体;">，增加一台</span>webserver<span style="font-family: 宋体;">时，会碰到一些问题，典型的有：</span><br />
1<span style="font-family: 宋体;">、如何让访问分配到这两台机器上，这个时候通常会考虑的方案是</span>Apache<span style="font-family: 宋体;">自带的负载均衡方案，或</span>LVS<span style="font-family: 宋体;">这类的软件负载均衡方案；</span><br />
2<span style="font-family: 宋体;">、如何保持状态信息的同步，例如用户</span><span onclick="tagshow(event)">session</span><span style="font-family: 宋体;">等，这个时候会考虑的方案有写入数据库、写入存储、</span><span onclick="tagshow(event)">cookie</span><span style="font-family: 宋体;">或同步</span>session<span style="font-family: 宋体;">信息等机制等；</span><br />
3<span style="font-family: 宋体;">、如何保持数据缓存信息的同步，例如之前缓存的用户数据等，这个时候通常会考虑的机制有缓存同步或分布式缓存；</span><br />
4<span style="font-family: 宋体;">、如何让上传文件这些类似的功能继续正常，这个时候通常会考虑的机制是使用共享文件系统或存储等；</span><br />
<span style="font-family: 宋体;">在解决了这些问题后，终于是把</span>webserver<span style="font-family: 宋体;">增加为了两台，系统终于是又恢复到了以往的速度。</span><br />
<span style="font-family: 宋体;">看看这一步完成后系统的图示：</span><br />
<img src="http://www.blogjava.net/images/blogjava_net/bluedavy/arch/5.PNG" border="0" alt="" width="341" height="244" /></p>
<p><span style="font-family: 宋体;">这一步涉及到了这些知识体系：</span><br />
<span style="font-family: 宋体;">负载均衡技术（包括但不限于硬件负载均衡、软件负载均衡、负载算法、</span>linux<span style="font-family: 宋体;">转发协议、所选用的技术的实现细节等）、主备技术（包括但不限于</span>ARP<span style="font-family: 宋体;">欺骗、</span>linux heart-beat<span style="font-family: 宋体;">等）、状态信息或缓存同步技术（包括但不限于</span>Cookie<span style="font-family: 宋体;">技术、</span>UDP<span style="font-family: 宋体;">协议、状态信息广播、所选用的缓存同步技术的实现细节等）、共享文件技术（包括但不限于</span>NFS<span style="font-family: 宋体;">等）、存储技术（包括但不限于存储设备等）。</span></p>
<p><strong><span style="font-family: 宋体;"><span style="font-size: 14pt;">架构演变第六步：分库<br />
</span></span></strong><br />
<span style="font-family: 宋体;">享受了一段时间的系统访问量高速增长的幸福后，发现系统又开始变慢了，这次又是什么状况呢，经过查找，发现数据库写入、更新的这些操作的部分数据库连接的</span> <span style="font-family: 宋体;">资 源竞争非常激烈，导致了系统变慢，这下怎么办呢，此时可选的方案有数据库集群和分库策略，集群方面像有些数据库支持的并不是很好，因此分库会成为比较普遍 的策略，分库也就意味着要对原有程序进行修改，一通修改实现分库后，不错，目标达到了，系统恢复甚至速度比以前还快了。</span><br />
<span style="font-family: 宋体;">看看这一步完成后系统的图示：</span><br />
<img src="http://www.blogjava.net/images/blogjava_net/bluedavy/arch/6.PNG" border="0" alt="" width="341" height="243" /></p>
<p><span style="font-family: 宋体;">这一步涉及到了这些知识体系：</span><br />
<span style="font-family: 宋体;">这一步更多的是需要从业务上做合理的划分，以实现分库，具体技术细节上没有其他的要求；</span><br />
<span style="font-family: 宋体;">但同时随着数据量的增大和分库的进行，在数据库的设计、调优以及维护上需要做的更好，因此对这些方面的技术还是提出了很高的要求的。</span></p>
<p><strong><span style="font-family: 宋体;"><span style="font-size: 14pt;"><span style="font-family: 宋体;">架构演变第七步：分表、</span>DAL<span style="font-family: 宋体;">和分布式缓存</span></span></span></strong><br />
<strong><span style="font-family: 宋体;"><span style="font-size: 14pt;"><br />
</span></span></strong><br />
<span style="font-family: 宋体;">随着系统的不断运行，数据量开始大幅度增长，这个时候发现分库后查询仍然会有些慢，于是按照分库的思想开始做分表的工作，当然，这不可避免的会需要对程序</span> <span style="font-family: 宋体;">进行一些修改，也许在这个时候就会发现应用自己要关心分库分表的规则等，还是有些复杂的，于是萌生能否增加一个通用的框架来实现分库分表的数据访问，这个在</span>ebay<span style="font-family: 宋体;">的架构中对应的就是</span>DAL<span style="font-family: 宋体;">，这个演变的过程相对而言需要花费较长的时间，当然，也有可能这个通用的框架会等到分表做完后才开始做，同时，在这个阶段可</span> <span style="font-family: 宋体;">能会发现之前的缓存同步方案出现问题，因为数据量太大，导致现在不太可能将缓存存在本地，然后同步的方式，需要采用分布式缓存方案了，于是，又是一通考察和折磨，终于是将大量的数据缓存转移到分布式缓存上了。</span><br />
<span style="font-family: 宋体;">看看这一步完成后系统的图示：</span><br />
<img src="http://www.blogjava.net/images/blogjava_net/bluedavy/arch/7.PNG" border="0" alt="" width="342" height="439" /></p>
<p><span style="font-family: 宋体;">这一步涉及到了这些知识体系：</span><br />
<span style="font-family: 宋体;">分表更多的同样是业务上的划分，技术上涉及到的会有动态</span><span onclick="tagshow(event)">hash</span><span style="font-family: 宋体;">算法、</span>consistent hash<span style="font-family: 宋体;">算法等；</span><br />
DAL<span style="font-family: 宋体;">涉及到比较多的复杂技术，例如数据库连接的管理（超时、异常）、数据库操作的控制（超时、异常）、分库分表规则的封装等；</span></p>
<p><strong><span style="font-family: 宋体;"><span style="font-size: 14pt;"><span style="font-family: 宋体;">架构演变第八步：增加更多的</span>webserver</span></span></strong><br />
<strong><span style="font-family: 宋体;"><span style="font-size: 14pt;"><br />
</span></span></strong><br />
<span style="font-family: 宋体;">在做完分库分表这些工作后，数据库上的压力已经降到比较低了，又开始过着每天看着访问量暴增的幸福生活了，突然有一天，发现系统的访问又开始有变慢的趋势</span> <span style="font-family: 宋体;">了，这个时候首先查看数据库，压力一切正常，之后查看</span>webserver<span style="font-family: 宋体;">，发现</span><span onclick="tagshow(event)">apache</span><span style="font-family: 宋体;">阻塞了很多的请求，而应用<span onclick="tagshow(event)">服务器</span>对每个请求也是比较快的，看来</span> <span style="font-family: 宋体;">是请求数太高导致需要排队等待，响应速度变慢，这还好办，一般来说，这个时候也会有些钱了，于是添加一些</span>webserver<span style="font-family: 宋体;">服务器，在这个添加</span> webserver<span style="font-family: 宋体;">服务器的过程，有可能会出现几种挑战：</span><br />
1<span style="font-family: 宋体;">、</span>Apache<span style="font-family: 宋体;">的软负载或</span>LVS<span style="font-family: 宋体;">软负载等无法承担巨大的</span>web<span style="font-family: 宋体;">访问量（请求连接数、网络流量等）的调度了，这个时候如果经费允许的话，会采取的方案是购</span> <span style="font-family: 宋体;">买硬件负载，例如</span>F5<span style="font-family: 宋体;">、</span>Netsclar<span style="font-family: 宋体;">、</span>Athelon<span style="font-family: 宋体;">之类的，如经费不允许的话，会采取的方案是将应用从逻辑上做一定的分类，然后分散到不同的软负载集群中；</span><br />
2<span style="font-family: 宋体;">、原有的一些状态信息同步、文件共享等方案可能会出现瓶颈，需要进行改进，也许这个时候会根据情况编写符合网站业务需求的分布式文件系统等；</span><br />
<span style="font-family: 宋体;">在做完这些工作后，开始进入一个看似完美的无限伸缩的时代，当网站流量增加时，应对的解决方案就是不断的添加</span>webserver<span style="font-family: 宋体;">。</span><br />
<span style="font-family: 宋体;">看看这一步完成后系统的图示：</span></p>
<p><img src="http://www.blogjava.net/images/blogjava_net/bluedavy/arch/8.PNG" border="0" alt="" width="466" height="441" /></p>
<p><span style="font-family: 宋体;">这一步涉及到了这些知识体系：</span><br />
<span style="font-family: 宋体;">到了这一步，随着机器数的不断增长、数据量的不断增长和对系统可用性的要求越来越高，这个时候要求对所采用的技术都要有更为深入的理解，并需要根据网站的需求来做更加定制性质的产品。</span></p>
<p><strong><span style="font-family: 宋体;"><span style="font-size: 14pt;">架构演变第九步：数据读写分离和廉价存储方案</span></span></strong><br />
<strong><span style="font-family: 宋体;"><br />
</span></strong><br />
<span style="font-family: 宋体;">突然有一天，发现这个完美的时代也要结束了，数据库的噩梦又一次出现在眼前了，由于添加的</span>webserver<span style="font-family: 宋体;">太多了，导致数据库连接的资源还是不够用，而这个时候又已经分库分表了，开始分析数据库的压力状况，可能会发现数据库的读写比很高，这个时候通常会想到数据读写分离的方案，当然，这个方案要实现并不</span> <span style="font-family: 宋体;">容易，另外，可能会发现一些数据存储在数据库上有些浪费，或者说过于占用数据库资源，因此在这个阶段可能会形成的架构演变是实现数据读写分离，同时编写一些更为廉价的存储方案，例如</span>BigTable<span style="font-family: 宋体;">这种。</span><br />
<span style="font-family: 宋体;">看看这一步完成后系统的图示：</span></p>
<p><img src="http://www.blogjava.net/images/blogjava_net/bluedavy/arch/9.PNG" border="0" alt="" width="555" height="398" /></p>
<p><span style="font-family: 宋体;">这一步涉及到了这些知识体系：</span><br />
<span style="font-family: 宋体;">数据读写分离要求对数据库的复制、</span>standby<span style="font-family: 宋体;">等策略有深入的掌握和理解，同时会要求具备自行实现的技术；</span><br />
<span style="font-family: 宋体;">廉价存储方案要求对</span>OS<span style="font-family: 宋体;">的文件存储有深入的掌握和理解，同时要求对采用的语言在文件这块的实现有深入的掌握。</span></p>
<p><strong><span style="font-family: 宋体;"><span style="font-size: 14pt;">架构演变第十步：进入大型分布式应用时代和廉价服务器群梦想时代</span></span></strong><br />
<strong><span style="font-family: 宋体;"><br />
</span></strong><br />
<span style="font-family: 宋体;">经过上面这个漫长而痛苦的过程，终于是再度迎来了完美的时代，不断的增加</span>webserver<span style="font-family: 宋体;">就可以支撑越来越高的访问量了，对于大型网站而言，人气的重要毋</span> <span style="font-family: 宋体;">庸置疑，随着人气的越来越高，各种各样的功能需求也开始爆发性的增长，这个时候突然发现，原来部署在</span>webserver<span style="font-family: 宋体;">上的那个</span>web<span style="font-family: 宋体;">应用已经非常庞大</span> <span style="font-family: 宋体;">了，当多个团队都开始对其进行改动时，可真是相当的不方便，复用性也相当糟糕，基本是每个团队都做了或多或少重复的事情，而且部署和维护也是相当的麻烦，</span> <span style="font-family: 宋体;">因为庞大的应用包在</span>N<span style="font-family: 宋体;">台机器上复制、启动都需要耗费不少的时间，出问题的时候也不是很好查，另外一个更糟糕的状况是很有可能会出现某个应用上的</span>bug<span style="font-family: 宋体;">就导</span> <span style="font-family: 宋体;">致了全站都不可用，还有其他的像调优不好操作（因为机器上部署的应用什么都要做，根本就无法进行针对性的调优）等因素，根据这样的分析，开始痛下决心，将</span> <span style="font-family: 宋体;">系统根据职责进行拆分，于是一个大型的分布式应用就诞生了，通常，这个步骤需要耗费相当长的时间，因为会碰到很多的挑战：</span><br />
1<span style="font-family: 宋体;">、拆成分布式后需要提供一个高性能、稳定的通信框架，并且需要支持多种不同的通信和远程调用方式；</span><br />
2<span style="font-family: 宋体;">、将一个庞大的应用拆分需要耗费很长的时间，需要进行业务的整理和系统依赖关系的控制等；</span><br />
3<span style="font-family: 宋体;">、如何运维（依赖管理、运行状况管理、错误追踪、调优、监控和报警等）好这个庞大的分布式应用。</span><br />
<span style="font-family: 宋体;">经过这一步，差不多系统的架构进入相对稳定的阶段，同时也能开始采用大量的廉价机器来支撑着巨大的访问量和数据量，结合这套架构以及这么多次演变过程吸取的经验来采用其他各种各样的方法来支撑着越来越高的访问量。</span><br />
<span style="font-family: 宋体;">看看这一步完成后系统的图示：</span><br />
<img src="http://www.blogjava.net/images/blogjava_net/bluedavy/arch/10.PNG" border="0" alt="" width="554" height="431" /></p>
<p><span style="font-family: 宋体;">这一步涉及到了这些知识体系：</span><br />
<span style="font-family: 宋体;">这一步涉及的知识体系非常的多，要求对通信、远程调用、消息机制等有深入的理解和掌握，要求的都是从理论、硬件级、操作系统级以及所采用的语言的实现都有清楚的理解。</span><br />
<span style="font-family: 宋体;">运维这块涉及的知识体系也非常的多，多数情况下需要掌握分布式并行计算、报表、监控技术以及规则策略等等。</span><br />
<span style="font-family: 宋体;">说起来确实不怎么费力，整个网站架构的经典演变过程都和上面比较的类似，当然，每步采取的方案，演变的步骤有可能有不同，另外，由于网站的业务不同，会有不同的专业技术的需求，这篇</span>b<span onclick="tagshow(event)">log</span><span style="font-family: 宋体;">更多的是从架构的角度来讲解演变的过程，当然，其中还有很多的技术也未在此提及，像数据库集群、数据挖掘、搜索等，但在真实的演变过程中还会借助像提升硬件配置、网络环境、改造操作系统、</span>CDN<span style="font-family: 宋体;">镜像等来支撑更大的流量，因此在真实的发展过程中还会有很多的不同，另外一个大型网站要做到的远远不仅仅上面这些，还有像安全、运维、运营、服务、存储等，要做好一个大型的网站真的很不容易，写这篇文章更多的是希望能够引出更多大型网站架构演变的介绍，:-)</span><span style="font-family: 宋体;">。</span></p>
<p>ps:最后附上几篇LiveJournal架构演变的文章：<br />
从LiveJournal后台发展看大规模网站性能优化方法<br />
<a href="http://blog.zhangjianfeng.com/article/743" target="_blank"><span style="text-decoration: underline;"><span style="color: #0000ff;">http://blog.zhangjianfeng.com/article/743</span></span></a></p>
<p>另外从这里：<a href="http://www.danga.com/words/" target="_blank"><span style="text-decoration: underline;"><span style="color: #0000ff;">http://www.danga.com/words/</span></span></a>大家可以找到更多关于现在LiveJournal网站架构的介绍。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.terrysco.com/node/web-arch-knowledge.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[转] Web架构设计经验分享</title>
		<link>http://www.terrysco.com/node/web-exp-share.html</link>
		<comments>http://www.terrysco.com/node/web-exp-share.html#comments</comments>
		<pubDate>Tue, 12 Feb 2008 14:33:08 +0000</pubDate>
		<dc:creator>terrysco</dc:creator>
				<category><![CDATA[Web Architecture]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.terrysco.com/?p=253</guid>
		<description><![CDATA[作者：朱燚 来源：http://www.cnblogs.com/yizhu2000/archive/2007/12/04/982142.html 本人作为一位web工程师，着眼最多之处莫过于 性能与架构，本次幸得参与sd2.0大会，得以与同行广泛交流,于此二方面，有些心得，不敢独享，与众博友分享，本文是这次参会与众同撩交流的心得，有兴趣者可以查看视频 架构设计的几个心得： 一，不要过设计：never over design 这是一个常常被提及的话题，但是 只要想想你的架构里有多少功能是根本没有用到，或者最后废弃的，就能明白其重要性了，初涉架构设计，往往倾向于设计大而化一的架构，希望设计出具有无比扩 展性，能适应一切需求的增加架构，web开发领域是个非常动态的过程，我们很难预测下个星期的变化，而又需要对变化做出最快最有效的响应。。 ebay的工程师说过，他们的架构设计从来都不能满足系统的增长，所以他们的系统永远都在推翻重做。请注意，不是ebay架构师的能力有问题，他们 设计的架构总是建立旧版本的瓶颈上，希望通过新的架构带来突破，然而新架构带来的突破总是在很短的时间内就被新增需求淹没，于是他们不得不又使用新的架构 web开发，是个非常敏捷的过程，变化随时都在产生，用户需求千变万化，许多方面偶然性非常高，较之软件开发，希望用一个架构规划以后的所有设计，是不现实的 二，web架构生命周期：web architecture‘s life cycle 既然要杜绝过设计，又要保证一定的前瞻性，那么怎么才能找到其中的平衡呢？希望下面的web架构生命周期能够帮到你 所设计的架构需要在1－10倍的增长下，通过简单的增加硬件容量就能够胜任，而在5－10倍的增长期间，请着手下一个版本的架构设计，使之能承受下一个10倍间的增长 google之所以能够称霸，不完全是因为搜索技术和排序技术有多先进，其实包括baidu和yahoo，所使用的技术现在也已经大同小异，然而，google能在一个月内通过增加上万台服务器来达到足够系统容量的能力确是很难被复制的 三，缓存：Cache 空间换取时间，缓存永远计算机设计的重中之重，从cpu到io，到处都可以看到缓存的身影，web架构设计重，缓存设计必不可少，关于怎样 设计合理的缓存，jbosscache的创始人，淘宝的创始人是这样说的：其实设计web缓存和企业级缓存是非常不同的，企业级缓存偏重于逻辑，而web 缓存，简单快速为好。。 缓存带来的问题是什么？是程序的复杂度上升，因为数据散布在多个进程，所以同步就是一个麻烦的问题，加上集群，复杂度会进一步提高，在实际运用中，采用怎样的同步策略常常需要和业务绑定 老钱为搜狐设计的帖子设计了链表缓存，这样既可以满足灵活插入的需要，又能够快速阅读，而其他一些大型社区也经常采用类此的结构来优化帖子列表，memcache也是一个常常用到的工具 钱宏武谈架构设计视频 http://211.100.26.82/CSDN_Live/140/qhw.flv Cache的常用的策略是：让数据在内存中，而不是在比较耗时的磁盘上。从这个角度讲，mysql提供的heap引擎（存储方式）也是一个值得思考的方法,这种存储方法可以把数据存储在内存中,并且保留sql强大的查询能力,是不是一举两得呢? 我们这里只说到了读缓存，其实还有一种写缓存，在以内容为主的社区里比较少用到，因为这样的社区最主要需要解决的问题是读问题，但是在处理能力低于 请求能力时，或者单个希望请求先被缓存形成块，然后批量处理时，写缓存就出现了，在交互性很强的社区设计里我们很容易找到这样的缓存 四，核心模块一定要自己开发：DIY your core module 这点我们是深有体会，钱宏武和云风也都有谈到，我们经常倾向于使用一些开源模块，如果不涉及核心模块，确实是可以的，如果涉及，那么就要小 心了，因为当访问量达到一定的程度，这些模块往往都有这样那样的问题，当然我们可以把问题归结为对开源的模块不熟悉，但是不管怎样，核心出现问题的时候， 不能完全掌握其代码是非常可怕的 五，合理选择数据存储方式：reasonable data storage 我们一定要使用数据库吗，不一定，雷鸣告诉我们搜索不一定需要数据库，云风告诉我们，游戏不一定需要数据库，那么什么时候我们才需要数据库呢，为什么不干脆用文件来代替他呢？ 首先我们需要先承认，数据库也是对文件进行操作。我们需要数据库，主要是使用下面这几个功能，一个是数据存储，一个是数据检索，在关系数据库中，我们其实非常在乎数据库的复杂搜索的能力，看看一个统计用的tsql就知道了(不用仔细读,扫一眼就可以了) select   c.Class_name,d.Class_name_2,a.Creativity_Title,b.User_name,(select   count(Id)   from   review   where   Reviewid=a.Id)   as   countNum   from   Creativity   [...]]]></description>
			<content:encoded><![CDATA[<p>作者：朱燚<br />
来源：<a href="http://www.cnblogs.com/yizhu2000/archive/2007/12/04/982142.html">http://www.cnblogs.com/yizhu2000/archive/2007/12/04/982142.html</a></p>
<p>本人作为一位web工程师，着眼最多之处莫过于 性能与架构，本次幸得参与sd2.0大会，得以与同行广泛交流,于此二方面，有些心得，不敢独享，与众博友分享，本文是这次参会与众同撩交流的心得，有兴趣者可以查看视频</p>
<p>架构设计的几个心得：</p>
<p><strong><br />
一，不要过设计：never over design<br />
</strong><br />
这是一个常常被提及的话题，但是 只要想想你的架构里有多少功能是根本没有用到，或者最后废弃的，就能明白其重要性了，初涉架构设计，往往倾向于设计大而化一的架构，希望设计出具有无比扩 展性，能适应一切需求的增加架构，web开发领域是个非常动态的过程，我们很难预测下个星期的变化，而又需要对变化做出最快最有效的响应。。</p>
<p>ebay的工程师说过，他们的架构设计从来都不能满足系统的增长，所以他们的系统永远都在推翻重做。请注意，不是ebay架构师的能力有问题，他们 设计的架构总是建立旧版本的瓶颈上，希望通过新的架构带来突破，然而新架构带来的突破总是在很短的时间内就被新增需求淹没，于是他们不得不又使用新的架构<br />
web开发，是个非常敏捷的过程，变化随时都在产生，用户需求千变万化，许多方面偶然性非常高，较之软件开发，希望用一个架构规划以后的所有设计，是不现实的</p>
<p><strong>二，web架构生命周期：web architecture‘s life cycle</strong><br />
既然要杜绝过设计，又要保证一定的前瞻性，那么怎么才能找到其中的平衡呢？希望下面的web架构生命周期能够帮到你</p>
<p><a href="http://images.cnblogs.com/cnblogs_com/yizhu2000/WindowsLiveWriter/web_8D00/architecture_life_cycle.gif"><img src="http://images.cnblogs.com/cnblogs_com/yizhu2000/WindowsLiveWriter/web_8D00/architecture_life_cycle_thumb.gif" alt="architecture_life_cycle" width="734" height="242" /></a></p>
<p>所设计的架构需要在1－10倍的增长下，通过简单的增加硬件容量就能够胜任，而在5－10倍的增长期间，请着手下一个版本的架构设计，使之能承受下一个10倍间的增长</p>
<p>google之所以能够称霸，不完全是因为搜索技术和排序技术有多先进，其实包括baidu和yahoo，所使用的技术现在也已经大同小异，然而，google能在一个月内通过增加上万台服务器来达到足够系统容量的能力确是很难被复制的</p>
<p><strong><br />
三，缓存：Cache</strong><br />
空间换取时间，缓存永远计算机设计的重中之重，从cpu到io，到处都可以看到缓存的身影，web架构设计重，缓存设计必不可少，关于怎样 设计合理的缓存，jbosscache的创始人，淘宝的创始人是这样说的：其实设计web缓存和企业级缓存是非常不同的，企业级缓存偏重于逻辑，而web 缓存，简单快速为好。。</p>
<p>缓存带来的问题是什么？是程序的复杂度上升，因为数据散布在多个进程，所以同步就是一个麻烦的问题，加上集群，复杂度会进一步提高，在实际运用中，采用怎样的同步策略常常需要和业务绑定</p>
<p>老钱为搜狐设计的帖子设计了链表缓存，这样既可以满足灵活插入的需要，又能够快速阅读，而其他一些大型社区也经常采用类此的结构来优化帖子列表，memcache也是一个常常用到的工具</p>
<p>钱宏武谈架构设计视频 <a href="http://211.100.26.82/CSDN_Live/140/qhw.flv"><span style="text-decoration: underline;"><span style="color: #0000ff;">http://211.100.26.82/CSDN_Live/140/qhw.flv</span></span></a></p>
<p>Cache的常用的策略是：让数据在内存中，而不是在比较耗时的磁盘上。从这个角度讲，mysql提供的heap引擎（存储方式）也是一个值得思考的方法,这种存储方法可以把数据存储在内存中,并且保留sql强大的查询能力,是不是一举两得呢?</p>
<p>我们这里只说到了读缓存，其实还有一种写缓存，在以内容为主的社区里比较少用到，因为这样的社区最主要需要解决的问题是读问题，但是在处理能力低于 请求能力时，或者单个希望请求先被缓存形成块，然后批量处理时，写缓存就出现了，在交互性很强的社区设计里我们很容易找到这样的缓存</p>
<p><strong>四，核心模块一定要自己开发：DIY your core module</strong><br />
这点我们是深有体会，钱宏武和云风也都有谈到，我们经常倾向于使用一些开源模块，如果不涉及核心模块，确实是可以的，如果涉及，那么就要小 心了，因为当访问量达到一定的程度，这些模块往往都有这样那样的问题，当然我们可以把问题归结为对开源的模块不熟悉，但是不管怎样，核心出现问题的时候， 不能完全掌握其代码是非常可怕的</p>
<p><strong><br />
五，合理选择数据存储方式：reasonable data storage</strong><br />
我们一定要使用数据库吗，不一定，雷鸣告诉我们搜索不一定需要数据库，云风告诉我们，游戏不一定需要数据库，那么什么时候我们才需要数据库呢，为什么不干脆用文件来代替他呢？<br />
首先我们需要先承认，数据库也是对文件进行操作。我们需要数据库，主要是使用下面这几个功能，一个是数据存储，一个是数据检索，在关系数据库中，我们其实非常在乎数据库的复杂搜索的能力，看看一个统计用的tsql就知道了(不用仔细读,扫一眼就可以了)</p>
<p>select   c.Class_name,d.Class_name_2,a.Creativity_Title,b.User_name,(select   count(Id)   from   review   where   Reviewid=a.Id)   as   countNum   from   Creativity   as   a,User_info   as   b,class   as   c,class2   as   d   where   a.user_id=b.id   and   a.Creativity_Class=c.Id   and   a.Creativity_Class_2=d.Id<br />
select   a.Id,max(c.Class_name),(max(d.Class_name_2),max(a.Creativity_Title),max(b.User_name),count(e.Id)   as   countNum   from   Creativity   as   a,User_info   as   b,class   as   c,class2   as   d,review   as   e   where   a.user_id=b.id   and   a.Creativity_Class=c.Id   and   a.Creativity_Class_2=d.Id   and   a.Id=e.Reviewid   group   by   a.Id &#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;.</p>
<p>我们可以看出需要数据库关联，排序的能力，这个能力在某些情况下非常重要，但是如果你的网站的常规操作，全是这样复杂的逻辑，那效率一定是非常低 的，所以我们常常在数据库里加入许多冗余字段，来减小简单查询时关联等操作带来的压力，我们看看下面这张图，可以看到数据库的设计重心，和网站(指内容型 社区)需要面对的问题实际是有一些偏差的</p>
<p><a href="http://images.cnblogs.com/cnblogs_com/yizhu2000/WindowsLiveWriter/web_8D00/database.gif"><img style="width: 588px; height: 411px;" src="http://images.cnblogs.com/cnblogs_com/yizhu2000/WindowsLiveWriter/web_8D00/database_thumb.gif" alt="database" width="664" height="495" /></a></p>
<p>同样其他一些软件产品也遇到同样的问题所以具我了解，有许多特殊的运用都有自己设计的特殊数据存储结构与方法，比如有的大型服务程序采取树形数据存储结构，lucene使用文件来存储索引和文件</p>
<p>从另外一个角度上看，使用数据库，意味着数据和表现是完全分离的（这当然是经典的设计思路），也就是说当需要展示数据时，不得不需要一个转换的过 程，也可以说是绑定的过程，当网站具备一定规模的时候，数据库往往成为效率的瓶颈，所以许多网站也采用直接书写静态文件的方法来避免读取操作时的绑定</p>
<p>这并不是说我们从今天起就可以把我们亲爱的数据库打入冷宫，而是我们在设计数据的持久化时，需要根据实际情况来选择存储方式，而数据库不过是其中一个选项</p>
<p><strong><br />
六，搞清楚谁是最重要的人：who&#8217;s the most important guy</strong><br />
在用例需求分析的时候常常讲到涉众，就是和你的设计息息相关的人，在web中我们一定以为最重要的涉众莫过于用户了。，在一个传统的互动社 区开发中，最重要的东西是内容，用户产生内容，所以用户就是上帝，至于内容挑选工具，不就是给坐我后面三排的妹妹们用的吗？凑或行了，实在有问题我就在数 据里手动帮你加得了。。这大概是眼下许多小型甚至中型网站技术人员的普遍想法。钱宏武在他的讲座里谈到了这个问题：实际上网站每天产生的内容非常的多，普 通人是不可能看完的，而编辑负责把精华的内容推荐到首页上，所以很多用户读到的内容其实都依赖于编辑的推荐，所以设计让编辑工作方便的工具也是非常重要， 有时甚至是最重要的。</p>
<p><strong><br />
七，不要执着于文档：don&#8217;t be crazy about document</strong><br />
web开发的文档重要吗？什么文档最重要？我的看法是web开发中交流<strong>&gt;</strong>文档，</p>
<p>现在大的软件公司比较流行的做法是：<br />
注重产品设计文档，在这种方法里，产品文档非常详尽，并且没有歧义，开发人员基于设计文档开发，测试人员基于设计文档制定测试方案，任何新人都可以通过阅读产品设计文档来了解项目的概况</p>
<p>而web项目从概念到实现的时间是非常短的，而且越短越好，并且由于变化迅速，要想写出完整的产品和需求文档是几乎不可能的，大多数情况是等你写出 完备的文档，项目早就是另外一个样子，但是没有文档的问题是，如果团队发生变化，添加新成员怎样才能了解软件的结构和概念呢，一种是每个人都了解软件的整 个结构，除非你的团队整体消失，否则任何一个人都能够担当培养新人的责任，这种face2face交流比文档有效率很多。</p>
<p>于是就有了前office开发者，现任yahoo中国某产品开发负责人的刘振飞所感觉到的落差，他说，<strong>我们的项目是吵出来的</strong>，我听完会心一笑</p>
<p><strong><br />
八，团队：team</strong><br />
不要专家团队，而要外科手术式的团队,你的团队里一定要有清道夫，需要有弓箭手，让他们和项目一起成长，才是项目负责人的最大成就</p>
<p><strong> </strong></p>
<p><strong>总结：</strong></p>
<p>0)架构是一种权衡</p>
<p><a href="http://images.cnblogs.com/cnblogs_com/yizhu2000/WindowsLiveWriter/web_8D00/architecture.gif"><img src="http://images.cnblogs.com/cnblogs_com/yizhu2000/WindowsLiveWriter/web_8D00/architecture_thumb.gif" alt="architecture" width="368" height="272" /></a></p>
<p>1)web开发的特点是是：没有太复杂的技术难点，一切在于迅速的把握需求，其实这正式敏捷开发的要旨所在，一切都可以非常快速的建立，非常快速的重构，我们的开发工具，底层库和框架，包括搜索引擎和web文档提供的帮助，都提我们供给了敏捷的能力。</p>
<p>2)此外，相应的，最有效率的交流方式必须留给web开发，那就是face2face（面对面），不要太担心你的设计不能被完备的文档所保留下来，他们会以交流，代码和小卡片的方式保存下来</p>
<p>3)人的因素会更加重要，无论是对用户的需求，还是开发人员的素质。</p>
<p>另：有关web效率，有著名的14条规则，由yahoo性能效率小组所总结，并广为流传。业已出现相关插件（<a href="http://download.csdn.net/source/299494"><span style="text-decoration: underline;"><span style="color: #0000ff;">YSlow</span></span></a>），针对具体网页按彼规则评分，这次该小组负责人Tenni Theurer也受邀来到此次大会，我把Tenni小姐（之前真的没有想到她是个女孩，并且如此年轻）和她的团队的14 rules列在下面</p>
<div>
<li><a href="http://developer.yahoo.com/performance/rules.html#num_http"><span style="text-decoration: underline;"><span style="color: #0000ff;">Make Fewer HTTP Requests</span></span></a></li>
<li><a href="http://developer.yahoo.com/performance/rules.html#cdn"><span style="text-decoration: underline;"><span style="color: #0000ff;">Use a Content Delivery Network</span></span></a></li>
<li><a href="http://developer.yahoo.com/performance/rules.html#expires"><span style="text-decoration: underline;"><span style="color: #0000ff;">Add an Expires Header</span></span></a></li>
<li><a href="http://developer.yahoo.com/performance/rules.html#gzip"><span style="text-decoration: underline;"><span style="color: #0000ff;">Gzip Components</span></span></a></li>
<li><a href="http://developer.yahoo.com/performance/rules.html#css_top"><span style="text-decoration: underline;"><span style="color: #0000ff;">Put CSS at the Top</span></span></a></li>
<li><a href="http://developer.yahoo.com/performance/rules.html#js_bottom"><span style="text-decoration: underline;"><span style="color: #0000ff;">Move Scripts to the Bottom</span></span></a></li>
<li><a href="http://developer.yahoo.com/performance/rules.html#css_expressions"><span style="text-decoration: underline;"><span style="color: #0000ff;">Avoid CSS Expressions</span></span></a></li>
<li><a href="http://developer.yahoo.com/performance/rules.html#external"><span style="text-decoration: underline;"><span style="color: #0000ff;">Make JavaScript and CSS External</span></span></a></li>
<li><a href="http://developer.yahoo.com/performance/rules.html#dns_lookups"><span style="text-decoration: underline;"><span style="color: #0000ff;">Reduce DNS Lookups</span></span></a></li>
<li><a href="http://developer.yahoo.com/performance/rules.html#minify"><span style="text-decoration: underline;"><span style="color: #0000ff;">Minify JavaScript</span></span></a></li>
<li><a href="http://developer.yahoo.com/performance/rules.html#redirects"><span style="text-decoration: underline;"><span style="color: #0000ff;">Avoid Redirects</span></span></a></li>
<li><a href="http://developer.yahoo.com/performance/rules.html#js_dupes"><span style="text-decoration: underline;"><span style="color: #0000ff;">Remove Duplicate Scripts</span></span></a></li>
<li><a href="http://developer.yahoo.com/performance/rules.html#etags"><span style="text-decoration: underline;"><span style="color: #0000ff;">Configure ETags</span></span></a></li>
<li><a href="http://developer.yahoo.com/performance/rules.html#cacheajax"><span style="text-decoration: underline;"><span style="color: #0000ff;">Make Ajax Cacheable</span></span></a>通过安装<a href="http://download.csdn.net/source/299505"><span style="text-decoration: underline;"><span style="color: #0000ff;">firebug</span></span></a>和<a href="http://download.csdn.net/source/299494"><span style="text-decoration: underline;"><span style="color: #0000ff;">YSlow</span></span></a>这两个firefox插件(请注意要先安装firebug再安装yslow,下载后拖动到firefox里即可)我们可以看到你的网页根据下面的规则的评分,这是我在博客园博客首页的评分截图,上面D表示总分,下面是单项评分,A最好F最差,不知道还有没有G <img src='http://www.terrysco.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />
<p><a href="http://images.cnblogs.com/cnblogs_com/yizhu2000/WindowsLiveWriter/web_8D00/YSlow.gif"><img style="width: 458px; height: 467px;" src="http://images.cnblogs.com/cnblogs_com/yizhu2000/WindowsLiveWriter/web_8D00/YSlow_thumb.gif" alt="YSlow" width="474" height="467" /></a></li>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.terrysco.com/node/web-exp-share.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>大型Web2.0站点构建技术初探</title>
		<link>http://www.terrysco.com/node/web2-arch.html</link>
		<comments>http://www.terrysco.com/node/web2-arch.html#comments</comments>
		<pubDate>Sat, 19 Jan 2008 19:44:41 +0000</pubDate>
		<dc:creator>terrysco</dc:creator>
				<category><![CDATA[Web Architecture]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.terrysco.com/?p=265</guid>
		<description><![CDATA[来源：http://blog.csdn.net/guxianga/archive/2007/09/19/1791131.aspx 一、 web2.0网站常用可用性功能模块分析 二、 Flickr的幕后故事 三、 YouTube 的架构扩展 四、 mixi.jp：使用开源软件搭建的可扩展SNS网站 五、 Technorati的后台数据库架构 六、 通过了解MySpace的六次重构经历,来认识分布式系统到底该如何创建 七、 从LiveJournal后台发展看大规模网站性能优化方法 八、 说说大型高并发高负载网站的系统架构 一、 web2.0网站常用可用性功能模块分析 Web 2.0网站是指将传统的网站构架（平台、内容源、用户、传播方式等）转化到以用户为核心的网站构架上来，包括一系列体现web2.0概念的元素、定位和创 意。web2.0网站在构架上须体现两大宗旨，即强大的后台系统和简单的前台页面，也即提供良好的用户体验，体现以人为本，技术服务人类的宗旨。 web2.0网站常用功能块通常包括以下几大项： 1. Tag标签功能块 Tag(中文叫做”标签”) 是一种新的组织和管理在线信息的方式。它不同于传统的、针对文件本身的关键字检索，而是一种模糊化、智能化的分类。 网页使用Tag标签的好处： 为页面设置一个或者多个Tag标签可以引导读者阅读更多相关文章，为别人带去流量同理也为自己带来流量。 可以帮助读者及时了解一些未知的概念和知识点，提高用户体验。 Tag是人的意志和趋向的体现，Tag可以帮助你找到兴趣相投的人。 基于以上优势，Tag标签代替了传统的分类法，成为web2.0网站使用率最高的功能块（与其说是功能块倒不如说是一种内容导航和内容组织形式）。 一句话：Tag标签是一种更灵活的分类方法，功能在于引导，特点是无处不在，体现智能性、模糊性和趋向性。 2. RSS订阅功能块 RSS是在线共享内容的一种简易方式（也叫聚合内容，Really Simple Syndication）。通常在时效性比较强的内容上使用RSS订阅能更快速获取信息，网站提供RSS输出，有利于让用户获取网站内容的最新更新。网络 用户可以在客户端借助于支持RSS的聚合工具软件（例如SharpReader,NewzCrawler、FeedDemon），在不打开网站内容页面的 情况下阅读支持RSS输出的网站内容。 RSS订阅的方式： 订阅到客户端软件如周伯通、遨游浏览器RSS阅读、Foxmail RSS阅读等，此方式使用者较多 订阅到在线阅读（聚合类）门户网站如Google Reader，Yahoo Reader，抓虾、Gougou等，省去了安装RSS阅读器的麻烦 订阅到在线单用户聚合器如Lilina等，比较灵活 RSS订阅功能的最大好处是定向投递，也就是说RSS机制更能体现用户的意愿和个性，获取信息的方式也最直接和简单，这是RSS订阅功能备受青睐的一大主要原因。 3. 推荐和收藏功能块 说到推荐功能，不仅web2.0网站在大量使用，传统的以cms平台为代表的内容模式的网站也在大量使用，推荐功能主要是指向一些网摘或者聚合类门户网站推荐自己所浏览到的网页。当然，一种变相的推荐就是阅读者的自我收藏行为，在共享的模式下也能起到推荐的作用。 比较有名的推荐目标有以del.icio.us为代表的网摘类网站包括国内比较有名气的365key、和讯网摘、新浪vivi、天极网摘等。这 里值得一提的是前段时间曾涌现了大批网摘类网站，但他们坚持活下来的好像没有几个了，推荐使用前面提到的这几个网摘门户，人气基本上是使最旺的。 4. [...]]]></description>
			<content:encoded><![CDATA[<p>来源：<a href="http://blog.csdn.net/guxianga/archive/2007/09/19/1791131.aspx">http://blog.csdn.net/guxianga/archive/2007/09/19/1791131.aspx</a></p>
<p><span style="color: #993300; font-size: large;"><strong><br />
</strong></span></p>
<div id="msgcns!f815ecd7b3d086d9!226">
<p>一、 web2.0网站常用可用性功能模块分析</p>
<p>二、 Flickr的幕后故事</p>
<p>三、 YouTube 的架构扩展</p>
<p>四、 mixi.jp：使用开源软件搭建的可扩展SNS网站</p>
<p>五、 Technorati的后台数据库架构</p>
<p>六、 通过了解MySpace的六次重构经历,来认识分布式系统到底该如何创建</p>
<p>七、 从LiveJournal后台发展看大规模网站性能优化方法</p>
<p>八、 说说大型高并发高负载网站的系统架构</p>
<h4>一、 <a><span style="color: #0066a7;">web2.0</span></a>网站常用可用性功能模块分析</h4>
<p>Web 2.0网站是指将传统的网站构架（平台、内容源、用户、传播方式等）转化到以用户为核心的网站构架上来，包括一系列体现web2.0概念的元素、定位和创 意。web2.0网站在构架上须体现两大宗旨，即强大的后台系统和简单的前台页面，也即提供良好的用户体验，体现以人为本，技术服务人类的宗旨。</p>
<p>web2.0网站常用功能块通常包括以下几大项：</p>
<p><strong>1.</strong> <strong>Tag</strong><strong>标签功能块</strong></p>
<p>Tag(中文叫做”标签”) 是一种新的组织和管理在线信息的方式。它不同于传统的、针对文件本身的关键字检索，而是一种模糊化、智能化的分类。</p>
<p>网页使用Tag标签的好处：</p>
<p>为页面设置一个或者多个Tag标签可以引导读者阅读更多相关文章，为别人带去流量同理也为自己带来流量。</p>
<p>可以帮助读者及时了解一些未知的概念和知识点，提高用户体验。</p>
<p>Tag是人的意志和趋向的体现，Tag可以帮助你找到兴趣相投的人。</p>
<p>基于以上优势，Tag标签代替了传统的分类法，成为web2.0网站使用率最高的功能块（与其说是功能块倒不如说是一种内容导航和内容组织形式）。</p>
<p>一句话：Tag标签是一种更灵活的分类方法，功能在于引导，特点是无处不在，体现智能性、模糊性和趋向性。</p>
<p><strong>2.</strong> <strong>RSS</strong><strong>订阅功能块</strong></p>
<p>RSS是在线共享内容的一种简易方式（也叫聚合内容，Really Simple Syndication）。通常在时效性比较强的内容上使用RSS订阅能更快速获取信息，网站提供RSS输出，有利于让用户获取网站内容的最新更新。网络 用户可以在客户端借助于支持RSS的聚合工具软件（例如SharpReader,NewzCrawler、FeedDemon），在不打开网站内容页面的 情况下阅读支持RSS输出的网站内容。</p>
<p>RSS订阅的方式：</p>
<p>订阅到客户端软件如周伯通、遨游浏览器RSS阅读、Foxmail RSS阅读等，此方式使用者较多</p>
<p>订阅到在线阅读（聚合类）门户网站如Google Reader，Yahoo Reader，抓虾、Gougou等，省去了安装RSS阅读器的麻烦</p>
<p>订阅到在线单用户聚合器如Lilina等，比较灵活</p>
<p>RSS订阅功能的最大好处是定向投递，也就是说RSS机制更能体现用户的意愿和个性，获取信息的方式也最直接和简单，这是RSS订阅功能备受青睐的一大主要原因。</p>
<p><strong>3.</strong> <strong>推荐和收藏功能块</strong></p>
<p>说到推荐功能，不仅web2.0网站在大量使用，传统的以cms平台为代表的内容模式的网站也在大量使用，推荐功能主要是指向一些网摘或者聚合类门户网站推荐自己所浏览到的网页。当然，一种变相的推荐就是阅读者的自我收藏行为，在共享的模式下也能起到推荐的作用。</p>
<p>比较有名的推荐目标有以del.icio.us为代表的网摘类网站包括国内比较有名气的365key、和讯网摘、新浪vivi、天极网摘等。这 里值得一提的是前段时间曾涌现了大批网摘类网站，但他们坚持活下来的好像没有几个了，推荐使用前面提到的这几个网摘门户，人气基本上是使最旺的。</p>
<p><strong>4.</strong> <strong>评论和留言功能块</strong></p>
<p>web2.0强调参与性，强调发挥用户的主导作用，这里的参与性除了所谓的订阅、推荐功能外更多地体现在用户对内容的评价和态度，这就要靠评论功能 块来完成。一个典型的web2.0网站或者说一个能体现人气的web2.0网站都会花大量篇幅来体现用户的观点和视觉。这里尤其要提到web2.0中的带 头老大web blog，评论功能已经成为博客主人与浏览者交流的主要阵地，是体现网站人气的最直观因素。</p>
<p>评论功能块应用在博客系统中实际上已经和博客内容相分离，而更好的应用恰恰是一些以点评为主的web2.0网站比如豆瓣、点评网等，这里的评论功能块直接制造了内容也极大地体现了网站的人气，所以说评论功能块是web2.0网站最有力的武器。</p>
<p><strong>5.</strong> <strong>站内搜索功能块</strong></p>
<p>搜索是信息来源最直接的方式之一，无论你的网站是否打上web2.0的烙印，搜索对于一个体系庞大、内容丰富的大型网站都是非常必要的。Tag 标签在某种程度上起到搜索的作用，它能够有效聚合以此Tag为关键词的内容，但这种情况的前提是此Tag标签对浏览者是可见的，也就是说当Tag标签摆在 浏览者的眼前时才成立，而对于那些浏览者想要的信息却没有Tag标签来引导时搜索就是达到此目的的最好方法。</p>
<p>对于web2.0网站，站内搜索以标题或者Tag为搜索域都能起到好的效果，但本人不建议使用内容搜索域，因为这不符合搜索的高效性原则。同 时，具有突出关键词的内容往往都可以用Tag标签来引导，因此使用内容域来搜索实际上是一种浪费服务器资源的行为，而且搜索结果的准确性将大打折扣。</p>
<p><strong>6.</strong> <strong>群组功能块</strong></p>
<p>我为什么要把群组作为web2.0网站的功能块来分析呢，因为群组是web2.0网站的一大特点，也是web2.0所要体现的服务宗旨所在。一 个web2.0网站，博客也好、播客也好、点评也好，抑或是网摘、聚合门户，他们都强调人的参与性。物以类聚、人以群分，每个参与者都有自己的兴趣趋 向，web2.0网站的另一主要功能就是帮助这些人找到同样兴趣的人并形成一个活跃的群体，这是web2.0网站的根本。</p>
<p>总结：web2.0网站倡导的是集体创作、共享资源，靠的是人气，体现的是参与性，一个没有参与性的web2.0网站都不足以成为web2.0。以 上提到的这几个功能块就是以吸引用户参与和引导用户参与为目的的，真正的web2.0不是什么深奥的东西，只有一点，那就是如何让浏览者沸腾起来。</p>
<h4><a><span style="color: #0066a7;">二、 Flickr</span></a>的幕后故事</h4>
<p>我们都看到 Flickr 的成功，而又有多少”精英”们了解过 Flickr 背后的过程是多么充满艰险。</p>
<p>Flickr 是全 CGI 的动态构架，并以一种 .gne 的脚本作为 CGI 程序语言。不管网站制作菜鸟还是高手都会疑惑：gne 是哪种程序语言？答案：gne 不是一种语言，Flickr 是以极为经典的 PHP + MySQL 方式实现的，在被 Yahoo 收购服务器搬入美国之前，使用了 21 台（69.90.111.101-121） Apache/PHP 做 Web、23 台图片服务器、另有 MySQL 服务器组成的数据库集群的服务器数量未知。现在估计使用的是 Yahoo 的负载均衡系统，对外只有一个 Web 的 IP 和图片服务器的 IP 了。</p>
<p>那为何 .php 的文件要改成 .gne 呢？以往有大型网站为向后兼容性考虑，隐藏以程序语言命名的脚本文件扩展名，比如 Baidu 隐藏了 .php（Google 的 http 服务器是自己写的，整合了脚本程序，个别页面是 .py&#8211;Python）；还有一些网站是改成自己网站名相关的扩展名，如 MSN 的群组则是 .msnw，榕树下是 .rs。</p>
<p>那 Flickr 的 gne 是什么意思？我在维基百科的 Flickr 条目上找到了答案(中文 Flickr 条目上没有写明) 。原来 GNE 是 Game NeverEnding 的缩写，Flickr 的开发者 Ludicorp 在 2002-2004 年一直在开发这套以 Game NerverEnding 为名称的大型多人在线角色扮演游戏&#8211;一套基于浏览器的 Web 游戏系统，个人以为应该就是当年九城的虚拟城市。但是开发近 3 年后该计划不得不破产，最终只发布了一个 Beta 版，而 Ludicorp 将这套系统稍加移植，就有了 Flickr。呵呵，原来 gne 是一个项目的名称。关于 GNE 的一些连接：http://del.icio.us/schee/gne。</p>
<p>早期的 Flickr 想做成在类似聊天室的地方让网友分享、交流自己的照片，注重社区形式和保护照片不被外部引用（见徐子涵2004年的文章），可能是看到了 Hello 的模式吧。但是聪明的 Flickr 团队不久就改变了策略，淡化了传统的社区形式&#8211;如聊天室、而加强了现在使其功成名就的 Tag 组织形式，一种更自由更随兴更轻松好玩的大社区形式，或者叫它广义社区吧，我随便叫的，可能太学究，看着别太在意就是了。另外，将原来照片只能在 Flash 内浏览的限制区除了，并大力推荐用户将照片引用到自己的 Blog，这无疑对于挑战传统相册系统有决定性意义。减少 Flash 后的网页更多地引进了新兴的 Ajax 技术，使界面操作变得非常 Cool。</p>
<p>这就是 Flickr 的历史，清晰地看到了他们对于优秀产品的执著。有了技术和经验积累，加上不断坚持，总有一天时来运转，你的产品会成为新潮流的里程碑。</p>
<p>还有一句话要告诉 Yupoo 等：把 Flickr 想成一个有 Tag 功能的在线相册就已经错远了；复制粘贴者们想当然将 Flickr 去其糟粕取其精华，结果无关紧要的拿来了，将令人激动的优点都去掉了，结果剩下什么？</p>
<h4><a><span style="color: #0066a7;">三、 YouTube</span></a> 的架构扩展</h4>
<p>在西雅图扩展性的技术研讨会上，YouTube 的 Cuong Do 做了关于 YouTube Scalability 的报告。视频内容在 Google Video 上有(地址)，可惜国内用户看不到。</p>
<p>Kyle Cordes 对这个视频中的内容做了介绍。里面有不少技术性的内容。值得分享一下。(Kyle Cordes 的介绍是本文的主要来源)</p>
<p>简单的说 YouTube 的数据流量, “一天的YouTube流量相当于发送750亿封电子邮件.”, 2006 年中就有消息说每日 PV 超过 1 亿,现在? 更夸张了,”每天有10亿次下载以及6,5000次上传”, 真假姑且不论, 的确是超乎寻常的海量. 国内的互联网应用,但从数据量来看,怕是只有 51.com 有这个规模. 但技术上和 YouTube 就没法子比了.</p>
<p><strong>1.</strong> <strong>Web</strong> <strong>服务器</strong></p>
<p>YouTube 出于开发速度的考虑，大部分代码都是 Python 开发的。Web 服务器有部分是 Apache， 用 FastCGI 模式。对于视频内容则用 Lighttpd 。据我所知，MySpace 也有部分服务器用 Lighttpd ，但量不大。YouTube 是 Lighttpd 最成功的案例。(国内用 Lighttpd 站点不多，豆瓣用的比较舒服。by Fenng)</p>
<p><strong>2.</strong> <strong>视频</strong></p>
<p>视频的缩略图(Thumbnails)给服务器带来了很大的挑战。每个视频平均有4个缩略图，而每个 Web 页面上更是有多个，每秒钟因为这个带来的磁盘 IO 请求太大。YouTube 技术人员启用了单独的服务器群组来承担这个压力，并且针对 Cache 和 OS 做了部分优化。另一方面，缩略图请求的压力导致 Lighttpd 性能下降。通过 Hack Lighttpd 增加更多的 worker 线程很大程度解决了问题。而最新的解决方案是起用了 Google 的 BigTable， 这下子从性能、容错、缓存上都有更好表现。看人家这收购的，好钢用在了刀刃上。</p>
<p>出于冗余的考虑，每个视频文件放在一组迷你 Cluster 上，所谓 “迷你 Cluster” 就是一组具有相同内容的服务器。最火的视频放在 CDN 上，这样自己的服务器只需要承担一些”漏网”的随即访问即可。YouTube 使用简单、廉价、通用的硬件，这一点和 Google 风格倒是一致。至于维护手段，也都是常见的工具，如 rsync, SSH 等，只不过人家更手熟罢了。</p>
<p><strong>3.</strong> <strong>数据库</strong></p>
<p>YouTube 用 MySQL 存储元数据&#8211;用户信息、视频信息什么的。数据库服务器曾经一度遇到 SWAP 颠簸的问题，解决办法是删掉了 SWAP 分区! 管用。</p>
<p>最初的 DB 只有 10 块硬盘，RAID 10 ，后来追加了一组 RAID 1。够省的。这一波 Web 2.0 公司很少有用 Oracle 的(我知道的只有 Bebo,参见这里). 在扩展性方面，路线也是和其他站点类似，复制，分散 IO。最终的解决之道是”分区”,这个不是数据库层面的表分区，而是业务层面的分区(在用户名字或者 ID 上做文章,应用程序控制查找机制)</p>
<p>YouTube 也用 Memcached.</p>
<p>很想了解一下国内 Web 2.0 网站的数据信息,有谁可以提供一点 ?</p>
<h4><a><span style="color: #0066a7;">四、 mixi.jp</span></a>：使用开源软件搭建的可扩展SNS网站</h4>
<p>Mixi目前是日本排名第三的网站，全球排名42，主要提供SNS服务：日记，群组，站内消息，评论，相册等等，是日本最大的SNS网站。Mixi 从2003年12月份开始开发，由现在它的CTO &#8211; Batara Kesuma一个人焊，焊了四个月，在2004年2月份开始上线运行。两个月后就注册了1w用户，日访问量60wPV。在随后的一年里，用户增长到了 21w，第二年，增长到了200w。到今年四月份已经增长到370w注册用户，并且还在以每天1.5w人的注册量增长。这些用户中70%是活跃用户（活跃 用户：三天内至少登录一次的用户），平均每个用户每周在线时间为将近3个半小时。</p>
<p>下面我们来看它的技术架构。Mixi采用开源软件作为架构的基础：Linux 2.6，Apache 2.0，MySQL，Perl 5.8，memcached，Squid等等。到目前为止已经有100多台MySQL数据库服务器，并且在以每月10多台的速度增长。Mixi的数据库连 接方式采用的是每次查询都进行连接，而不是持久连接。数据库大多数是以InnoDB方式运行。Mixi解决扩展问题主要依赖于对数据库的切分。</p>
<p>首先进行垂直切分，按照表的内容将不同的表划分到不同的数据库中。然后是水平切分，根据用户的ID将不同用户的内容再划分的不同的数据库中，这是比 较通常的做法，也很管用。划分的关键还是在于应用中的实现，需要将操作封装在在数据层，而尽量不影响业务层。当然完全不改变逻辑层也不可能，这时候最能检 验以前的设计是否到位，如果以前设计的不错，那创建连接的时候传个表名，用户ID进去差不多就解决问题了，而以前如果sql代码到处飞，或者数据层封装的 不太好的话那就累了。</p>
<p>这样做了以后并不能从根本上解决问题，尤其是对于像mixi这种SNS网站，页面上往往需要引用大量的用户信息，好友信息，图片，文章信息，跨表， 跨库操作相当多。这个时候就需要发挥memcached的作用了，用大内存把这些不变的数据全都缓存起来，而当修改时就通知cache过期，这样应用层基 本上就可以解决大部分问题了，只会有很小一部分请求穿透应用层，用到数据库。Mixi的经验是平均每个页面的加载时间在0.02秒左右（当然根据页面大小 情况不尽相似），可以说明这种做法是行之有效的。Mixi一共在32台机器上有缓存服务器，每个Cache Server 2G内存，这些Cache Server与App Server装在一起。因为Cache Server对CPU消耗不大，而有了Cache Server的支援，App Server对内存要求也不是太高，所以可以和平共处，更有效的利用资源。</p>
<p>图片的处理就显得相对简单的多了。对于mixi而言，图像主要有两部分：一部分是经常要使用到的，像用户头像，群组的头像等等，大概有100多 GB，它们被Squid和CDN所缓存，命中率相对比较高；另一部分是用户上传的大量照片，它们的个体访问量相对而言比较小，命中率也比较低，使用 Cache不划算，所以对于这些照片的策略是直接在用户上传的时候分发到到图片存储服务器上，在用户访问的时候直接进行访问，当然图片的位置需要在数据库 中进行记录，不然找不到放在哪台服务器上就郁闷了。</p>
<h4><a><span style="color: #0066a7;">五、 Technorati</span></a>的后台数据库架构</h4>
<p><a href="http://www.technorati.com/"><span style="color: #0066a7;">Technorati</span></a> (现在被阻尼了, 可能你访问不了)的 <a href="http://www.mysqluc.com/cs/mysqluc2006/view/e_spkr/2216"><span style="color: #0066a7;">Dorion Carroll</span></a>在 <a href="http://www.mysqluc.com/"><span style="color: #0066a7;">2006 MySQL 用户会议</span></a>上介绍了一些关于 Technorati 后台数据库架构的情况.</p>
<p><strong>基本情况</strong></p>
<p>目前处理着大约 10Tb 核心数据, 分布在大约 20 台机器上.通过复制, 多增加了 100Tb 数据, 分布在 200 台机器上. 每天增长的数据 1TB. 通过 SOA 的运用, 物理与逻辑的访问相隔离,　似乎消除了数据库的瓶颈. 值得一提的是, 该扩展过程始终是利用普通的硬件与开源软件来完成的. 毕竟 , Web 2.0 站点都不是烧钱的主. 从数据量来看，这绝对是一个相对比较大的 Web 2.0 应用.</p>
<p>Tag 是 Technorati 最为重要的数据元素. 爆炸性的 Tag 增长给 Technorati 带来了不小的挑战.</p>
<p>2005 年 1 月的时候, 只有两台数据库服务器, 一主一从. 到了 06 年一月份, 已经是一主一从, 6 台 MyISAM 从数据库用来对付查询, 3 台 MyISAM 用作异步计算.</p>
<p>一些核心的处理方法:</p>
<p>1) <strong>根据实体(tags/posttags))</strong><strong>进行分区</strong></p>
<p>衡量数据访问方法，读和写的平衡.然后通过不同的维度进行分区．( Technorati 数据更新不会很多, 否则会成为数据库灾难)</p>
<p>2) <strong>合理利用 InnoDB</strong> <strong>与 MyISAM</strong></p>
<p>InnoDB 用于数据完整性/写性能要求比较高的应用. MyISAM 适合进行 OLAP 运算. 物尽其用.</p>
<p>3) <strong>MySQL</strong> <strong>复制</strong></p>
<p>复制数据到从主数据库到辅数据库上,平衡分布查询与异步计算, 另外一个功能是提供冗余． 如图:</p>
<p><a href="http://byfiles.storage.msn.com/y1pLfC-bv1f71MD7KAzVUgnp_rN0Fi1MvV55D6Ts-HPSOuY_VWl-b_5TeUo5jVasgIDPY2Jn0yjh-4"><img style="border-width: 0px;" src="http://www.360doc.com/DownloadImg/3500/754206_1" border="0" alt="clip_image002[4]" width="240" height="175" /></a></p>
<p><a><span style="color: #0066a7;">六、 通过了解MySpace</span></a>的六次重构经历,来认识分布式系统到底该如何创建.</p>
<p>在每个里程碑，站点负担都会超过底层系统部分组件的最大载荷，特别是数据库和存储系统。接着，功能出现问题，用户失声尖叫。最后，技术团队必须为此修订系统策略。</p>
<p>虽然自2005年早期，站点账户数超过7百万后，系统架构到目前为止保持了相对稳定，但MySpace仍然在为SQL Server支持的同时连接数等方面继续攻坚，Benedetto说，”我们已经尽可能把事情做到最好”。</p>
<p><strong>1.</strong> <strong>里程碑一：50</strong><strong>万账户</strong></p>
<p>按Benedetto 的说法，MySpace最初的系统很小，只有两台Web服务器和一个数据库服务器。那时使用的是Dell双CPU、4G内存的系统。</p>
<p>单个数据库就意味着所有数据都存储在一个地方，再由两台Web服务器分担处理用户请求的工作量。但就像MySpace后来的几次底层系统修订时 的情况一样，三服务器架构很快不堪重负。此后一个时期内，MySpace基本是通过添置更多Web服务器来对付用户暴增问题的。</p>
<p>但到在2004年早期，MySpace用户数增长到50万后，数据库服务器也已开始汗流浃背。</p>
<p>但和Web服务器不同，增加数据库可没那么简单。如果一个站点由多个数据库支持，设计者必须考虑的是，如何在保证数据一致性的前提下，让多个数据库分担压力。</p>
<p>在第二代架构中，MySpace运行在3个SQL Server数据库服务器上&#8211;一个为主，所有的新数据都向它提交，然后由它复制到其他两个；另两个全力向用户供给数据，用以在博客和个人资料栏显示。这 种方式在一段时间内效果很好&#8211;只要增加数据库服务器，加大硬盘，就可以应对用户数和访问量的增加。</p>
<p><strong>2.</strong> <strong>里程碑二：1-2</strong><strong>百万账户</strong></p>
<p>MySpace注册数到达1百万至2百万区间后，数据库服务器开始受制于I/O容量&#8211;即它们存取数据的速度。而当时才是2004年中，距离上次数 据库系统调整不过数月。用户的提交请求被阻塞，就像千人乐迷要挤进只能容纳几百人的夜总会，站点开始遭遇”主要矛盾”，Benedetto说，这意味着 MySpace永远都会轻度落后于用户需求。</p>
<p>“有人花5分钟都无法完成留言，因此用户总是抱怨说网站已经完蛋了。”他补充道。</p>
<p>这一次的数据库架构按照垂直分割模式设计，不同的数据库服务于站点的不同功能，如登录、用户资料和博客。于是，站点的扩展性问题看似又可以告一段落了，可以歇一阵子。</p>
<p>垂直分割策略利于多个数据库分担访问压力，当用户要求增加新功能时，MySpace将投入新的数据库予以支持它。账户到达2百万 后，MySpace还从存储设备与数据库服务器直接交互的方式切换到SAN（Storage Area Network，存储区域网络）&#8211;用高带宽、专门设计的网络将大量磁盘存储设备连接在一起，而数据库连接到SAN。这项措施极大提升了系统性能、正常运 行时间和可靠性，Benedetto说。</p>
<p><strong>3.</strong> <strong>里程碑三：3</strong><strong>百万账户</strong></p>
<p>当用户继续增加到3百万后，垂直分割策略也开始难以为继。尽管站点的各个应用被设计得高度独立，但有些信息必须共享。在这个架构里，每个数据库 必须有各自的用户表副本&#8211;MySpace授权用户的电子花名册。这就意味着一个用户注册时，该条账户记录必须在9个不同数据库上分别创建。但在个别情况 下，如果其中某台数据库服务器临时不可到达，对应事务就会失败，从而造成账户非完全创建，最终导致此用户的该项服务无效。</p>
<p>另外一个问题是，个别应用如博客增长太快，那么专门为它服务的数据库就有巨大压力。</p>
<p>2004年中，MySpace面临Web开发者称之为”向上扩展”对”向外扩展”（译者注：Scale Up和Scale Out，也称硬件扩展和软件扩展）的抉择&#8211;要么扩展到更大更强、也更昂贵的服务器上，要么部署大量相对便宜的服务器来分担数据库压力。一般来说，大型站 点倾向于向外扩展，因为这将让它们得以保留通过增加服务器以提升系统能力的后路。</p>
<p>但成功地向外扩展架构必须解决复杂的分布式计算问题，大型站点如Google、Yahoo和Amazon.com，都必须自行研发大量相关技术。以Google为例，它构建了自己的分布式文件系统。</p>
<p>另外，向外扩展策略还需要大量重写原来软件，以保证系统能在分布式服务器上运行。”搞不好，开发人员的所有工作都将白费”，Benedetto说。</p>
<p>因此，MySpace首先将重点放在了向上扩展上，花费了大约1个半月时间研究升级到32CPU服务器以管理更大数据库的问题。Benedetto说，”那时候，这个方案看似可能解决一切问题。”如稳定性，更棒的是对现有软件几乎没有改动要求。</p>
<p>糟糕的是，高端服务器极其昂贵，是购置同样处理能力和内存速度的多台服务器总和的很多倍。而且，站点架构师预测，从长期来看，即便是巨型数据库，最后也会不堪重负，Benedetto说，”换句话讲，只要增长趋势存在，我们最后无论如何都要走上向外扩展的道路。”</p>
<p>因此，MySpace最终将目光移到分布式计算架构&#8211;它在物理上分布的众多服务器，整体必须逻辑上等同于单台机器。拿数据库来说，就不能再像 过去那样将应用拆分，再以不同数据库分别支持，而必须将整个站点看作一个应用。现在，数据库模型里只有一个用户表，支持博客、个人资料和其他核心功能的数 据都存储在相同数据库。</p>
<p>既然所有的核心数据逻辑上都组织到一个数据库，那么MySpace必须找到新的办法以分担负荷&#8211;显然，运行在普通硬件上的单个数据库服务器是 无能为力的。这次，不再按站点功能和应用分割数据库，MySpace开始将它的用户按每百万一组分割，然后将各组的全部数据分别存入独立的SQL Server实例。目前，MySpace的每台数据库服务器实际运行两个SQL Server实例，也就是说每台服务器服务大约2百万用户。Benedetto指出，以后还可以按照这种模式以更小粒度划分架构，从而优化负荷分担。</p>
<p>当然，还是有一个特殊数据库保存了所有账户的名称和密码。用户登录后，保存了他们其他数据的数据库再接管服务。特殊数据库的用户表虽然庞大，但它只负责用户登录，功能单一，所以负荷还是比较容易控制的。</p>
<p><strong>4.</strong> <strong>里程碑四：9</strong><strong>百万到1</strong><strong>千7</strong><strong>百万账户</strong></p>
<p>2005年早期，账户达到9百万后，MySpace开始用Microsoft的C#编写ASP.NET程序。C#是C语言的最新派生语言，吸收了 C++和Java的优点，依托于Microsoft .NET框架（Microsoft为软件组件化和分布式计算而设计的模型架构）。ASP.NET则由编写Web站点脚本的ASP技术演化而来，是 Microsoft目前主推的Web站点编程环境。</p>
<p>可以说是立竿见影， MySpace马上就发现ASP.NET程序运行更有效率，与ColdFusion相比，完成同样任务需消耗的处理器能力更小。据技术总监 Whitcomb说，新代码需要150台服务器完成的工作，如果用ColdFusion则需要246台。Benedetto还指出，性能上升的另一个原因 可能是在变换软件平台，并用新语言重写代码的过程中，程序员复审并优化了一些功能流程。</p>
<p>最终，MySpace开始大规模迁移到ASP.NET。即便剩余的少部分ColdFusion代码，也从Cold-Fusion服务器搬到了 ASP.NET，因为他们得到了BlueDragon.NET（乔治亚州阿尔法利塔New Atlanta Communications公司的产品，它能将ColdFusion代码自动重新编译到Microsoft平台）的帮助。</p>
<p>账户达到1千万时，MySpace再次遭遇存储瓶颈问题。SAN的引入解决了早期一些性能问题，但站点目前的要求已经开始周期性超越SAN的I/O容量&#8211;即它从磁盘存储系统读写数据的极限速度。</p>
<p>原因之一是每数据库1百万账户的分割策略，通常情况下的确可以将压力均分到各台服务器，但现实并非一成不变。比如第七台账户数据库上线后，仅仅7天就被塞满了，主要原因是佛罗里达一个乐队的歌迷疯狂注册。</p>
<p>某个数据库可能因为任何原因，在任何时候遭遇主要负荷，这时，SAN中绑定到该数据库的磁盘存储设备簇就可能过载。”SAN让磁盘I/O能力大幅提升了，但将它们绑定到特定数据库的做法是错误的。”Benedetto说。</p>
<p>最初，MySpace通过定期重新分配SAN中数据，以让其更为均衡的方法基本解决了这个问题，但这是一个人工过程，”大概需要两个人全职工作。”Benedetto说。</p>
<p>长期解决方案是迁移到虚拟存储体系上，这样，整个SAN被当作一个巨型存储池，不再要求每个磁盘为特定应用服务。MySpace目前采用了一种新型SAN设备&#8211;来自加利福尼亚州弗里蒙特的3PARdata。</p>
<p>在3PAR的系统里，仍能在逻辑上按容量划分数据存储，但它不再被绑定到特定磁盘或磁盘簇，而是散布于大量磁盘。这就使均分数据访问负荷成为可 能。当数据库需要写入一组数据时，任何空闲磁盘都可以马上完成这项工作，而不再像以前那样阻塞在可能已经过载的磁盘阵列处。而且，因为多个磁盘都有数据副 本，读取数据时，也不会使SAN的任何组件过载。</p>
<p>当2005年春天账户数达到1千7百万时，MySpace又启用了新的策略以减轻存储系统压力，即增加数据缓存层&#8211;位于Web服务器和数据库 服务器之间，其唯一职能是在内存中建立被频繁请求数据对象的副本，如此一来，不访问数据库也可以向Web应用供给数据。换句话说，100个用户请求同一份 资料，以前需要查询数据库100次，而现在只需1次，其余都可从缓存数据中获得。当然如果页面变化，缓存的数据必须从内存擦除，然后重新从数据库获取&#8211; 但在此之前，数据库的压力已经大大减轻，整个站点的性能得到提升。</p>
<p>缓存区还为那些不需要记入数据库的数据提供了驿站，比如为跟踪用户会话而创建的临时文件&#8211;Benedetto坦言他需要在这方面补课，”我是数据库存储狂热分子，因此我总是想着将万事万物都存到数据库。”但将像会话跟踪这类的数据也存到数据库，站点将陷入泥沼。</p>
<p>增加缓存服务器是”一开始就应该做的事情，但我们成长太快，以致于没有时间坐下来好好研究这件事情。”Benedetto补充道。</p>
<p><strong>5.</strong> <strong>里程碑五：2</strong><strong>千6</strong><strong>百万账户</strong></p>
<p>2005年中期，服务账户数达到2千6百万时，MySpace切换到了还处于beta测试的SQL Server 2005。转换何太急？主流看法是2005版支持64位处理器。但Benedetto说，”这不是主要原因，尽管这也很重要；主要还是因为我们对内存的渴 求。”支持64位的数据库可以管理更多内存。</p>
<p>更多内存就意味着更高的性能和更大的容量。原来运行32位版本的SQL Server服务器，能同时使用的内存最多只有4G。切换到64位，就好像加粗了输水管的直径。升级到SQL Server 2005和64位Windows Server 2003后，MySpace每台服务器配备了32G内存，后于2006年再次将配置标准提升到64G。</p>
<p>意外错误</p>
<p>如果没有对系统架构的历次修改与升级，MySpace根本不可能走到今天。但是，为什么系统还经常吃撑着了？很多用户抱怨的”意外错误”是怎么引起的呢？</p>
<p>原因之一是MySpace对Microsoft的Web技术的应用已经进入连Microsoft自己也才刚刚开始探索的领域。比如11月，超出 SQL Server最大同时连接数，MySpace系统崩溃。Benedetto说，这类可能引发系统崩溃的情况大概三天才会出现一次，但仍然过于频繁了，以致 惹人恼怒。一旦数据库罢工，”无论这种情况什么时候发生，未缓存的数据都不能从SQL Server获得，那么你就必然看到一个&#8217;意外错误&#8217;提示。”他解释说。</p>
<p>去年夏天，MySpace的Windows 2003多次自动停止服务。后来发现是操作系统一个内置功能惹的祸&#8211;预防分布式拒绝服务攻击（黑客使用很多客户机向服务器发起大量连接请求，以致服务器 瘫痪）。MySpace和其他很多顶级大站点一样，肯定会经常遭受攻击，但它应该从网络级而不是依靠Windows本身的功能来解决问题&#8211;否则，大量 MySpace合法用户连接时也会引起服务器反击。</p>
<p>“我们花了大约一个月时间寻找Windows 2003服务器自动停止的原因。”Benedetto说。最后，通过Microsoft的帮助，他们才知道该怎么通知服务器：”别开枪，是友军。”</p>
<p>紧接着是在去年7月某个周日晚上，MySpace总部所在地洛杉矶停电，造成整个系统停运12小时。大型Web站点通常要在地理上分布配置多个 数据中心以预防单点故障。本来，MySpace还有其他两个数据中心以应对突发事件，但Web服务器都依赖于部署在洛杉矶的SAN。没有洛杉矶的 SAN，Web服务器除了恳求你耐心等待，不能提供任何服务。</p>
<p>Benedetto说，主数据中心的可靠性通过下列措施保证：可接入两张不同电网，另有后备电源和一台储备有30天燃料的发电机。但在这次事故中，不仅两张电网失效，而且在切换到备份电源的过程中，操作员烧掉了主动力线路。</p>
<p>2007年中，MySpace在另两个后备站点上也建设了SAN。这对分担负荷大有帮助&#8211;正常情况下，每个SAN都能负担三分之一的数据访问量。而在紧急情况下，任何一个站点都可以独立支撑整个服务，Benedetto说。</p>
<p>MySpace仍然在为提高稳定性奋斗，虽然很多用户表示了足够信任且能原谅偶现的错误页面。</p>
<p>“作为开发人员，我憎恶Bug，它太气人了。”Dan Tanner这个31岁的德克萨斯软件工程师说，他通过MySpace重新联系到了高中和大学同学。”不过，MySpace对我们的用处很大，因此我们可 以原谅偶发的故障和错误。” Tanner说，如果站点某天出现故障甚至崩溃，恢复以后他还是会继续使用。</p>
<p>这就是为什么Drew在论坛里咆哮时，大部分用户都告诉他应该保持平静，如果等几分钟，问题就会解决的原因。Drew无法平静，他写道，”我已 经两次给MySpace发邮件，而它说一小时前还是正常的，现在出了点问题……完全是一堆废话。”另一个用户回复说，”毕竟它是免费 的。”Benedetto坦承100%的可靠性不是他的目标。”它不是银行，而是一个免费的服务。”他说。</p>
<p>换句话说，MySpace的偶发故障可能造成某人最后更新的个人资料丢失，但并不意味着网站弄丢了用户的钱财。”关键是要认识到，与保证站点性 能相比，丢失少许数据的故障是可接受的。”Benedetto说。所以，MySpace甘冒丢失2分钟到2小时内任意点数据的危险，在SQL Server配置里延长了”checkpoint”操作&#8211;它将待更新数据永久记录到磁盘&#8211;的间隔时间，因为这样做可以加快数据库的运行。</p>
<p>Benedetto说，同样，开发人员还经常在几个小时内就完成构思、编码、测试和发布全过程。这有引入Bug的风险，但这样做可以更快实现新功 能。而且，因为进行大规模真实测试不具可行性，他们的测试通常是在仅以部分活跃用户为对象，且用户对软件新功能和改进不知就里的情况下进行的。因为事实上 不可能做真实的加载测试，他们做的测试通常都是针对站点。</p>
<p>“我们犯过大量错误，”Benedetto说，”但到头来，我认为我们做对的还是比做错的多。”</p>
<h4><a><span style="color: #0066a7;">七、 从LiveJournal</span></a>后台发展看大规模网站性能优化方法</h4>
<p><a href="http://www.livejournal.com/"><span style="color: #0066a7;">LiveJournal</span></a>是99年始于校园中的项目，几个人出于爱好做了这样一个应用，以实现以下功能：</p>
<ul>
<li>博客，论坛</li>
<li>社会性网络，找到朋友</li>
<li>聚合，把朋友的文章聚合在一起</li>
</ul>
<p>LiveJournal采用了大量的开源软件，甚至它本身也是一个开源软件。</p>
<p>在上线后，LiveJournal实现了非常快速的增长：</p>
<ul>
<li>2004年4月份：280万注册用户。</li>
<li>2005年4月份：680万注册用户。</li>
<li>2005年8月份：790万注册用户。</li>
<li>达到了每秒钟上千次的页面请求及处理。</li>
<li>使用了大量MySQL服务器。</li>
<li>使用了大量通用组件。</li>
</ul>
<p><strong>二、LiveJournal</strong><strong>架构现状概况</strong></p>
<p><a href="http://byfiles.storage.msn.com/y1pLfC-bv1f71Ng8NRsPI0kDc-Ikh9MpNQsQdk2hWYZj7EqSGMNCdy6_L0NCqVwf4Kdouk7Yyd1I7M"><img style="border-width: 0px;" src="http://www.360doc.com/DownloadImg/3500/754206_2" border="0" alt="clip_image004[4]" width="240" height="178" /></a></p>
<p><strong>三、从LiveJournal</strong><strong>发展中学习</strong></p>
<p>LiveJournal从1台服务器发展到100台服务器，这其中经历了无数的伤痛，但同时也摸索出了解决这些问题的方法，通过对LiveJournal的学习，可以让我们避免LJ曾经犯过的错误，并且从一开始就对系统进行良好的设计，以避免后期的痛苦。</p>
<p>下面我们一步一步看LJ发展的脚步。</p>
<p><strong>1</strong><strong>、一台服务器</strong></p>
<p>一台别人捐助的服务器，LJ最初就跑在上面，就像Google开始时候用的破服务器一样，值得我们尊敬。这个阶段，LJ的人以惊人的速度熟悉的 Unix的操作管理，服务器性能出现过问题，不过还好，可以通过一些小修小改应付过去。在这个阶段里LJ把CGI升级到了FastCGI。</p>
<p>最终问题出现了，网站越来越慢，已经无法通过优过化来解决的地步，需要更多的服务器，这时LJ开始提供付费服务，可能是想通过这些钱来购买新的服务器，以解决当时的困境。</p>
<p>毫无疑问，当时LJ存在巨大的单点问题，所有的东西都在那台服务器的铁皮盒子里装着。</p>
<p><a href="http://byfiles.storage.msn.com/y1pLfC-bv1f71P0Ctl55617UrDRVWacD8C-YyoV1p8Mjh3G3xC1ENgZFvH6K2cZYL18sYQf79Sx3uY"><img style="border-width: 0px;" src="http://www.360doc.com/DownloadImg/3500/754206_3" border="0" alt="clip_image006[4]" width="240" height="89" /></a></p>
<p><strong>2</strong><strong>、两台服务器</strong></p>
<p>用付费服务赚来的钱LJ买了两台服务器：一台叫做Kenny的Dell 6U机器用于提供Web服务，一台叫做Cartman的Dell 6U服务器用于提供数据库服务。</p>
<p><a href="http://byfiles.storage.msn.com/y1pLfC-bv1f71MYOwfHqsOqx2LZQeA6v74qsDAvbZorZpZFj2gr4fgXQOP3WxIdRovgimi1QAlsQKo"><img style="border-width: 0px;" src="http://www.360doc.com/DownloadImg/3500/754206_4" border="0" alt="clip_image008[4]" width="187" height="240" /></a></p>
<p>LJ有了更大的磁盘，更多的计算资源。但同时网络结构还是非常简单，每台机器两块网卡，Cartman通过内网为Kenny提供MySQL数据库服务。</p>
<p>暂时解决了负载的问题，新的问题又出现了：</p>
<ul>
<li>原来的一个单点变成了两个单点。</li>
<li>没有冷备份或热备份。</li>
<li>网站速度慢的问题又开始出现了，没办法，增长太快了。</li>
<li>Web服务器上CPU达到上限，需要更多的Web服务器。</li>
</ul>
<p><strong>3</strong><strong>、四台服务器</strong></p>
<p>又买了两台，Kyle和Stan，这次都是1U的，都用于提供Web服务。目前LJ一共有3台Web服务器和一台数据库服务器。这时需要在3台Web服务器上进行负载均横。</p>
<p><a href="http://byfiles.storage.msn.com/y1pLfC-bv1f71NbrJH5rdoo9Q6nZVx-GHS1h4I5aOqUMyFyTc55NtAnXQH_GQMklSqagAoLl7zoEww"><img style="border-width: 0px;" src="http://www.360doc.com/DownloadImg/3500/754206_5" border="0" alt="clip_image010[4]" width="240" height="115" /></a></p>
<p>LJ把Kenny用于外部的网关，使用mod_backhand进行负载均横。</p>
<p>然后问题又出现了：</p>
<ul>
<li>单点故障。数据库和用于做网关的Web服务器都是单点，一旦任何一台机器出现问题将导致所有服务不可用。虽然用于做网关的Web服务器可以通过保持心跳同步迅速切换，但还是无法解决数据库的单点，LJ当时也没做这个。</li>
<li>网站又变慢了，这次是因为IO和数据库的问题，问题是怎么往应用里面添加数据库呢？</li>
</ul>
<p><strong>4</strong><strong>、五台服务器</strong></p>
<p>又买了一台数据库服务器。在两台数据库服务器上使用了数据库同步(Mysql支持的Master-Slave模式)，写操作全部针对主数据库（通过Binlog，主服务器上的写操作可以迅速同步到从服务器上），读操作在两个数据库上同时进行(也算是负载均横的一种吧)。</p>
<p><a href="http://byfiles.storage.msn.com/y1pLfC-bv1f71N6odCri1KVxP_h3bcvZO-Hnp66GTpNHNZxnI4t4kfzDn7kQCzK-l7YwwyBR8BWcBU"><img style="border-width: 0px;" src="http://www.360doc.com/DownloadImg/3500/754206_6" border="0" alt="clip_image012[4]" width="240" height="127" /></a></p>
<p>实现同步时要注意几个事项：</p>
<ul>
<li>读操作数据库选择算法处理，要选一个当前负载轻一点的数据库。</li>
<li>在从数据库服务器上只能进行读操作</li>
<li>准备好应对同步过程中的延迟，处理不好可能会导致数据库同步的中断。只需要对写操作进行判断即可，读操作不存在同步问题。</li>
</ul>
<p><strong>5</strong><strong>、更多服务器</strong></p>
<p>有钱了，当然要多买些服务器。部署后快了没多久，又开始慢了。这次有更多的Web服务器，更多的数据库服务器，存在 IO与CPU争用。于是采用了BIG-IP作为负载均衡解决方案。</p>
<p><a href="http://byfiles.storage.msn.com/y1pLfC-bv1f71N3IagF7BfIWUPsYyeGzaDRWdW0UYgoESHvPFnoPcXbRayC0ujr6c_3EIcd5uQjeLM"><img style="border-width: 0px;" src="http://www.360doc.com/DownloadImg/3500/754206_7" border="0" alt="clip_image014[4]" width="225" height="240" /></a></p>
<p><strong>6</strong><strong>、现在我们在哪里：</strong></p>
<p><a href="http://byfiles.storage.msn.com/y1pLfC-bv1f71P3I0DKW-AYfsw9T4JlR-Ln3M8GJI3Mta9xvoKJ93LBpylAlMTlVU5v8gkKbVVExSU"><img style="border-width: 0px;" src="http://www.360doc.com/DownloadImg/3500/754206_8" border="0" alt="clip_image016[4]" width="240" height="142" /></a></p>
<p>现在服务器基本上够了，但性能还是有问题，原因出在架构上。</p>
<p>数据库的架构是最大的问题。由于增加的数据库都是以Slave模式添加到应用内，这样唯一的好处就是将读操作分布到了多台机器，但这样带来的后果就是写操作被大量分发，每台机器都要执行，服务器越多，浪费就越大，随着写操作的增加，用于服务读操作的资源越来越少。</p>
<p><a href="http://byfiles.storage.msn.com/y1pLfC-bv1f71MPya6rCW77VuC79TgWb_o4GOMvkefOyFMYGGKSUVWUw4MZCKw4rMtdIB1VRPgpQKg"><img style="border-width: 0px;" src="http://www.360doc.com/DownloadImg/3500/754206_9" border="0" alt="clip_image018[4]" width="240" height="93" /></a></p>
<p>由一台分布到两台</p>
<p><a href="http://byfiles.storage.msn.com/y1pLfC-bv1f71ML3RaIG8BvZTf5z0i_5ooooXQ0mQ6Qh4RD1iaj-qP0hY8b1ffaQKnVtz-kjhV42RM"><img style="border-width: 0px;" src="http://www.360doc.com/DownloadImg/3500/754206_10" border="0" alt="clip_image020[4]" width="240" height="131" /></a></p>
<p>最终效果</p>
<p>现在我们发现，我们并不需要把这些数据在如此多的服务器上都保留一份。服务器上已经做了RAID，数据库也进行了备份，这么多的备份完全是对资源的浪费，属于冗余极端过度。那为什么不把数据分布存储呢？</p>
<p>问题发现了，开始考虑如何解决。现在要做的就是把不同用户的数据分布到不同的服务器上进行存储，以实现数据的分布式存储，让每台机器只为相对固定的用户服务，以实现平行的架构和良好的可扩展性。</p>
<p>为了实现用户分组，我们需要为每一个用户分配一个组标记，用于标记此用户的数据存放在哪一组数据库服务器中。每组数据库由一个master及几个 slave组成，并且slave的数量在2-3台，以实现系统资源的最合理分配，既保证数据读操作分布，又避免数据过度冗余以及同步操作对系统资源的过度 消耗。</p>
<p><a href="http://byfiles.storage.msn.com/y1pLfC-bv1f71Pt9Hb_mHfbR9yubMZd0NMrk7Q_s1_RbC03CvTx-1yJEjgwRdkISUsWYw25yzSlX1w"><img style="border-width: 0px;" src="http://www.360doc.com/DownloadImg/3500/754206_11" border="0" alt="clip_image022[4]" width="240" height="155" /></a></p>
<p>由一台（一组）中心服务器提供用户分组控制。所有用户的分组信息都存储在这台机器上，所有针对用户的操作需要先查询这台机器得到用户的组号，然后再到相应的数据库组中获取数据。</p>
<p>这样的用户架构与目前LJ的架构已经很相像了。</p>
<p>在具体的实现时需要注意几个问题：</p>
<ul>
<li>在数据库组内不要使用自增ID，以便于以后在数据库组之间迁移用户，以实现更合理的I/O，磁盘空间及负载分布。</li>
<li>将userid，postid存储在全局服务器上，可以使用自增，数据库组中的相应值必须以全局服务器上的值为准。全局服务器上使用事务型数据库InnoDB。</li>
<li>在数据库组之间迁移用户时要万分小心，当迁移时用户不能有写操作。</li>
</ul>
<p><strong>7</strong><strong>、现在我们在哪里</strong></p>
<p><a href="http://byfiles.storage.msn.com/y1pLfC-bv1f71Pu4DMG0Os_qdTIzpK9fuMXimE3UUNik8HfzE8uLLktV0-AwIW3tULtxR4pUB1Lw9w"><img style="border-width: 0px;" src="http://www.360doc.com/DownloadImg/3500/754206_12" border="0" alt="clip_image024[4]" width="240" height="175" /></a></p>
<p>问题：</p>
<ul>
<li>一个全局主服务器，挂掉的话所有用户注册及写操作就挂掉。</li>
<li>每个数据库组一个主服务器，挂掉的话这组用户的写操作就挂掉。</li>
<li>数据库组从服务器挂掉的话会导致其它服务器负载过大。</li>
</ul>
<p>对于Master-Slave模式的单点问题，LJ采取了Master-Master模式来解决。所谓Master-Master实际上是人工实现的，并不是由MySQL直接提供的，实际上也就是两台机器同时是Master，也同时是Slave，互相同步。</p>
<p>Master-Master实现时需要注意：</p>
<ul>
<li>一个Master出错后恢复同步，最好由服务器自动完成。</li>
<li>数字分配，由于同时在两台机器上写，有些ID可能会冲突。</li>
</ul>
<p>解决方案：</p>
<ul>
<li>奇偶数分配ID，一台机器上写奇数，一台机器上写偶数</li>
<li>通过全局服务器进行分配(LJ采用的做法)。</li>
</ul>
<p>Master-Master模式还有一种用法，这种方法与前一种相比，仍然保持两台机器的同步，但只有一台机器提供服务（读和写），在每天晚上的时候进行轮换，或者出现问题的时候进行切换。</p>
<p><strong>8</strong><strong>、现在我们在哪里</strong></p>
<p><a href="http://byfiles.storage.msn.com/y1pLfC-bv1f71MZdrtXDHuDnf_tJozpHnLCL3UmzCGpqxOM9odGbkvKFUlPa_ydtTnif7Y9ffe1Af8"><img style="border-width: 0px;" src="http://www.360doc.com/DownloadImg/3500/754206_13" border="0" alt="clip_image026[4]" width="240" height="167" /></a></p>
<p>现在插播一条广告，MyISAM VS InnoDB。</p>
<p>使用InnoDB：</p>
<ul>
<li>支持事务</li>
<li>需要做更多的配置，不过值得，可以更安全的存储数据，以及得到更快的速度。</li>
</ul>
<p>使用MyISAM：</p>
<ul>
<li>记录日志（LJ用它来记网络访问日志）</li>
<li>存储只读静态数据，足够快。</li>
<li>并发性很差，无法同时读写数据（添加数据可以）</li>
<li>MySQL非正常关闭或死机时会导致索引错误，需要使用myisamchk修复，而且当访问量大时出现非常频繁。</li>
</ul>
<p><strong>9</strong><strong>、缓存</strong></p>
<p>去年我写过<a href="http://www.example.net.cn/archives/2006/01/eoamemcachedoea.html"><span style="color: #0066a7;">一篇文章介绍memcached</span></a>，它就是由LJ的团队开发的一款缓存工具，以key-value的方式将数据存储到分布的内存中。LJ缓存的数据：</p>
<ul>
<li>12台独立服务器（不是捐赠的）</li>
<li>28个实例</li>
<li>30GB总容量</li>
<li>90-93%的命中率（用过squid的人可能知道，squid内存加磁盘的命中率大概在70-80%）</li>
</ul>
<p>如何建立缓存策略？</p>
<p>想缓存所有的东西？那是不可能的，我们只需要缓存已经或者可能导致系统瓶颈的地方，最大程度的提交系统运行效率。通过对MySQL的日志的分析我们可以找到缓存的对象。</p>
<p>缓存的缺点？</p>
<ul>
<li>没有完美的事物，缓存也有缺点：</li>
<li>增大开发量，需要针对缓存处理编写特殊的代码。</li>
<li>管理难度增加，需要更多人参与系统维护。</li>
<li>当然大内存也需要钱。</li>
</ul>
<p><strong>10</strong><strong>、Web</strong><strong>访问负载均衡</strong></p>
<p>在数据包级别使用BIG-IP，但BIG-IP并不知道我们内部的处理机制，无法判断由哪台服务器对这些请求进行处理。反向代理并不能很好的起到作用，不是已经够快了，就是达不到我们想要的效果。</p>
<p>所以，LJ又开发了<a href="http://www.danga.com/perlbal/"><span style="color: #0066a7;">Perlbal</span></a>。特点：</p>
<ul>
<li>快，小，可管理的http web 服务器/代理</li>
<li>可以在内部进行转发</li>
<li>使用Perl开发</li>
<li>单线程，异步，基于事件，使用epoll , kqueue</li>
<li>支持Console管理与http远程管理，支持动态配置加载</li>
<li>多种模式：web服务器，反向代理，插件</li>
<li>支持插件：GIF/PNG互换？</li>
</ul>
<p><strong>11</strong><strong>、MogileFS</strong></p>
<p>LJ使用开源的<a href="http://www.danga.com/mogilefs/"><span style="color: #0066a7;">MogileFS</span></a>作为分布式文件存储系统。MogileFS使用非常简单，它的主要设计思想是：</p>
<ul>
<li>文件属于类（类是最小的复制单位）</li>
<li>跟踪文件存储位置</li>
<li>在不同主机上存储</li>
<li>使用MySQL集群统一存储分布信息</li>
<li>大容易廉价磁盘</li>
</ul>
<p>到目前为止就这么多了，更多文档可以在<a href="http://www.danga.com/words/"><span style="color: #0066a7;">http://www.danga.com/words/</span></a>找到。<a href="http://www.danga.com/"><span style="color: #0066a7;">Danga.com</span></a>和<a href="http://www.livejournal.com/"><span style="color: #0066a7;">LiveJournal.com</span></a>的 同学们拿这个文档参加了两次MySQL Con，两次OS Con，以及众多的其它会议，无私的把他们的经验分享出来，值得我们学习。在web2.0时代快速开发得到大家越来越多的重视，但良好的设计仍是每一个应 用的基础，希望web2.0们在成长为Top500网站的路上，不要因为架构阻碍了网站的发展。</p>
<h4><a><span style="color: #0066a7;"><strong>八、</strong> <strong>说说大型高并发高负载网站的系统架构</strong></span></a></h4>
<p>我在Cernet做过拨号接入平台的搭建，而后在Yahoo3721负载搜索引擎前端平台开发，又在猫扑处理过大型社区猫扑大杂烩的架构升级等工 作，同时自己接触和开发过不少大中型网站的模块，因此在大型网站应对高负载和并发的解决方案上有一些积累和经验，可以和大家一起探讨一下。</p>
<p>一个小型的网站，比如个人网站，可以使用最简单的html静态页面就实现了，配合一些图片达到美化效果，所有的页面均存放在一个目录下，这样的网站 对系统架构、性能的要求都很简单，随着互联网业务的不断丰富，网站相关的技术经过这些年的发展，已经细分到很细的方方面面，尤其对于大型网站来说，所采用 的技术更是涉及面非常广，从硬件到软件、编程语言、数据库、WebServer、防火墙等各个领域都有了很高的要求，已经不是原来简单的html静态网站 所能比拟的。</p>
<p>大型网站，比如门户网站。在面对大量用户访问、高并发请求方面，基本的解决方案集中在这样几个环节：使用高性能的服务器、高性能的数据库、高效率的编程语言、还有高性能的Web容器。但是除了这几个方面，还没法根本解决大型网站面临的高负载和高并发问题。</p>
<p>上面提供的几个解决思路在一定程度上也意味着更大的投入，并且这样的解决思路具备瓶颈，没有很好的扩展性，下面我从低成本、高性能和高扩张性的角度来说说我的一些经验。</p>
<p>1、HTML静态化</p>
<p>其实大家都知道，效率最高、消耗最小的就是纯静态化的html页面，所以我们尽可能使我们的网站上的页面采用静态页面来实现，这个最简单的方法其实 也是最有效的方法。但是对于大量内容并且频繁更新的网站，我们无法全部手动去挨个实现，于是出现了我们常见的信息发布系统CMS，像我们常访问的各个门户 站点的新闻频道，甚至他们的其他频道，都是通过信息发布系统来管理和实现的，信息发布系统可以实现最简单的信息录入自动生成静态页面，还能具备频道管理、 权限管理、自动抓取等功能，对于一个大型网站来说，拥有一套高效、可管理的CMS是必不可少的。</p>
<p>除了门户和信息发布类型的网站，对于交互性要求很高的社区类型网站来说，尽可能的静态化也是提高性能的必要手段，将社区内的帖子、文章进行实时的静态化，有更新的时候再重新静态化也是大量使用的策略，像Mop的大杂烩就是使用了这样的策略，网易社区等也是如此。</p>
<p>同时，html静态化也是某些缓存策略使用的手段，对于系统中频繁使用数据库查询但是内容更新很小的应用，可以考虑使用html静态化来实现，比如 论坛中论坛的公用设置信息，这些信息目前的主流论坛都可以进行后台管理并且存储再数据库中，这些信息其实大量被前台程序调用，但是更新频率很小，可以考虑 将这部分内容进行后台更新的时候进行静态化，这样避免了大量的数据库访问请求。</p>
<p>2、图片服务器分离</p>
<p>大家知道，对于Web服务器来说，不管是Apache、IIS还是其他容器，图片是最消耗资源的，于是我们有必要将图片与页面进行分离，这是基本上 大型网站都会采用的策略，他们都有独立的图片服务器，甚至很多台图片服务器。这样的架构可以降低提供页面访问请求的服务器系统压力，并且可以保证系统不会 因为图片问题而崩溃，在应用服务器和图片服务器上，可以进行不同的配置优化，比如apache在配置ContentType的时候可以尽量少支持，尽可能 少的LoadModule，保证更高的系统消耗和执行效率。</p>
<p>3、数据库集群和库表散列</p>
<p>大型网站都有复杂的应用，这些应用必须使用数据库，那么在面对大量访问的时候，数据库的瓶颈很快就能显现出来，这时一台数据库将很快无法满足应用，于是我们需要使用数据库集群或者库表散列。</p>
<p>在数据库集群方面，很多数据库都有自己的解决方案，Oracle、Sybase等都有很好的方案，常用的MySQL提供的Master/Slave也是类似的方案，您使用了什么样的DB，就参考相应的解决方案来实施即可。</p>
<p>上面提到的数据库集群由于在架构、成本、扩张性方面都会受到所采用DB类型的限制，于是我们需要从应用程序的角度来考虑改善系统架构，库表散列是常 用并且最有效的解决方案。我们在应用程序中安装业务和应用或者功能模块将数据库进行分离，不同的模块对应不同的数据库或者表，再按照一定的策略对某个页面 或者功能进行更小的数据库散列，比如用户表，按照用户ID进行表散列，这样就能够低成本的提升系统的性能并且有很好的扩展性。sohu的论坛就是采用了这 样的架构，将论坛的用户、设置、帖子等信息进行数据库分离，然后对帖子、用户按照板块和ID进行散列数据库和表，最终可以在配置文件中进行简单的配置便能 让系统随时增加一台低成本的数据库进来补充系统性能。</p>
<p>4、缓存</p>
<p>缓存一词搞技术的都接触过，很多地方用到缓存。网站架构和网站开发中的缓存也是非常重要。这里先讲述最基本的两种缓存。高级和分布式的缓存在后面讲述。</p>
<p>架构方面的缓存，对Apache比较熟悉的人都能知道Apache提供了自己的缓存模块，也可以使用外加的Squid模块进行缓存，这两种方式均可以有效的提高Apache的访问响应能力。</p>
<p>网站程序开发方面的缓存，Linux上提供的Memory Cache是常用的缓存接口，可以在web开发中使用，比如用Java开发的时候就可以调用MemoryCache对一些数据进行缓存和通讯共享，一些大 型社区使用了这样的架构。另外，在使用web语言开发的时候，各种语言基本都有自己的缓存模块和方法，PHP有Pear的Cache模块，Java就更多 了，.net不是很熟悉，相信也肯定有。</p>
<p>5、镜像</p>
<p>镜像是大型网站常采用的提高性能和数据安全性的方式，镜像的技术可以解决不同网络接入商和地域带来的用户访问速度差异，比如ChinaNet和 EduNet之间的差异就促使了很多网站在教育网内搭建镜像站点，数据进行定时更新或者实时更新。在镜像的细节技术方面，这里不阐述太深，有很多专业的现 成的解决架构和产品可选。也有廉价的通过软件实现的思路，比如Linux上的rsync等工具。</p>
<p>6、负载均衡</p>
<p>负载均衡将是大型网站解决高负荷访问和大量并发请求采用的终极解决办法。</p>
<p>负载均衡技术发展了多年，有很多专业的服务提供商和产品可以选择，我个人接触过一些解决方法，其中有两个架构可以给大家做参考。</p>
<ul>
<li>硬件四层交换</li>
</ul>
<p>第四层交换使用第三层和第四层信息包的报头信息，根据应用区间识别业务流，将整个区间段的业务流分配到合适的应用服务器进行处理。　第四层交换功能 就象是虚IP，指向物理服务器。它传输的业务服从的协议多种多样，有HTTP、FTP、NFS、Telnet或其他协议。这些业务在物理服务器基础上，需 要复杂的载量平衡算法。在IP世界，业务类型由终端TCP或UDP端口地址来决定，在第四层交换中的应用区间则由源端和终端IP地址、TCP和UDP端口 共同决定。</p>
<p>在硬件四层交换产品领域，有一些知名的产品可以选择，比如Alteon、F5等，这些产品很昂贵，但是物有所值，能够提供非常优秀的性能和很灵活的管理能力。Yahoo中国当初接近2000台服务器使用了三四台Alteon就搞定了。</p>
<ul>
<li>软件四层交换</li>
</ul>
<p>大家知道了硬件四层交换机的原理后，基于OSI模型来实现的软件四层交换也就应运而生，这样的解决方案实现的原理一致，不过性能稍差。但是满足一定量的压力还是游刃有余的，有人说软件实现方式其实更灵活，处理能力完全看你配置的熟悉能力。</p>
<p>软件四层交换我们可以使用Linux上常用的LVS来解决，LVS就是Linux Virtual Server，他提供了基于心跳线heartbeat的实时灾难应对解决方案，提高系统的鲁棒性，同时可供了灵活的虚拟VIP配置和管理功能，可以同时满 足多种应用需求，这对于分布式的系统来说必不可少。</p>
<p>一个典型的使用负载均衡的策略就是，在软件或者硬件四层交换的基础上搭建squid集群，这种思路在很多大型网站包括搜索引擎上被采用，这样的架构低成本、高性能还有很强的扩张性，随时往架构里面增减节点都非常容易。这样的架构我准备空了专门详细整理一下和大家探讨。</p>
<p>对于大型网站来说，前面提到的每个方法可能都会被同时使用到，我这里介绍得比较浅显，具体实现过程中很多细节还需要大家慢慢熟悉和体会，有时一个很小的squid参数或者apache参数设置，对于系统性能的影响就会很大，希望大家一起讨论，达到抛砖引玉之效。</p></div>
<p><a href="http://blog.csdn.net/guxianga/archive/2007/09/19/1791131.aspx"></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.terrysco.com/node/web2-arch.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

