高负载的Lamp架构

记得那时是2005年10月,开源小站刚上线不久的一篇文章。那时的我还仅仅将网站的高可用性和大负载,大流量集中在“堆硬件”的层面上。包括之后的一篇文档,似乎也没有逃脱这个范畴。之后由于工作内容的关系,始终没有再继续探讨这个问题。仅仅只在一篇关于GAE的文章中讲述了一下架构的趋势。

时隔了5年多,不妨回头重新从新的高度上说说LAMP结构的网站如何支撑尽可能大的负载。同样说明,本文代表站长Litrin的个人意见,欢迎共同探讨,但喷子慎入。

首先声明的是,以下一堆相对无趣的文字仅针对一系列负载到了至少10W pv以上级别,对于较小规模的网站大可不必遵守,还是提倡成本优先的原则,到了对应的PV级别想必也会有足够的财力和物力去改版了。

初期规划

这里主要还是指设计模型等前期工作。MVC的设计结构深入人心,不得不承认确实大多架构设计师首选的设计结构必是MVC。事实上,在一个网站上最容易获取,最不缺的资源是CPU和内存,最大的瓶颈都是出现在IO。

作为LAMP架构最大的问题就是MVC的代价太大,层层的封包意味着重复判断;打开大量的程序文件只会严重拖累性能。网上很多免费的、开源的PHP框架,用过的几个诸如ThinkPHP, ZF等应付中小型网站绝对没有问题,但都不适合大负载的网站。甚至包括Smarty这样单纯的模版引擎,大量的IO操作会拖累整体性能。如果不考虑其他因素,我甚至都考虑过All in 1的垃圾结构——这当然不现实。但恰恰是这种all in 1却正是大负载最适合的结构。奇怪的悖论。

受GAE的影响,曾经想过API+XML的方式实现网站架构,但后来打消了这个念头。XML本身的结构冗余度很多,这也就意味着信息承载率低。在内部几台服务器之间的通讯状况想必都没有必要搞XML,如果要搞类似的模式,CSV方式反倒是不错的选择。XML是为了开放给第三方用户的。

数据库设计

读写分离这个是众所周知的秘密了。Mysql 的Master + Slaver的设计真的很方便!最多就是多搞几重的读写分离。

拆表、拆库、分机器,大表做纵拆,宽表做横拆,不关联的分机器;纵拆是为了省时间,横拆是为了省内存,分机器是为了分负载。Mysql在几百万行数据级别以下性能是很不错的,超过这个数量级,就算机器再强悍都会死的很难看,mysql垃圾的锁表机制会展现无疑。没有人愿等到30秒以上的Respone,何况我曾经遭遇一个45分钟以上的Select操作(一重操作,没有用到Like,使用索引)。曾经用过mysql 的分区表,感觉这种方法更像是在打补丁——改变数据库结构去适应程序,很奇怪的流程,更何况即便逃过这次不拆,迟早有一天还会回来拆的。

索引,该有的全都有,但对于写操作频繁的表,索引反倒成了累赘,不要让索引数占到字段数的30%以上这是约定俗成的标准吧。

memcache,没什么可以多说的,这玩意基本上就是铺硬件换时间的。

说道非关系型数据库,好像近期很热门。怎么说呢?越是复杂的网站越是能体现出它的优势,但问题是大多数网站都不会像twitter或者Facebook这么复杂,况且大多数程序员的逻辑还是SQL模式,贸进很可能搞砸。

WWW服务器拓扑设计

F5这类的设备是必须的,之前曾经觉得LVS可以替代F5这样的设备。用过之后才发现,这等于是将整个网站的身价性命都扔到了一台服务器上,一旦宕机或者被侵入呢?

对于Apache还是nginx的争论持续了很久。nginx很快速,可以将单独的PHP负载分离出去,但没有apache来的灵活。要根据需求再做评价。

异步操作和缓存机制

这个貌似也没有什么花头,调整好负载之后可以将一部分操作异步到数据库相对空闲的时段进行,达到移峰填谷的效果。配合memcache或者其他的缓存机制本身也是动转静的手段之一。

自动和手动的问题

属于代码级别了吧。良好的编程规范对系统的优化是很显著的。漫山遍野的select *, 大量的变量不清空是高负载系统的忌讳。纵然php的内存处理机制再出色,它永远也不会理解你设置的变量什么时候失效,减少这看似寥寥无几的空间乘上惊人的pv数也是很可观的。

推荐阅读:
之前写过一篇关于syslog的
今天有个同事在配置Apache
想必各位平时在用任何网络设备的
很多情况下,我们往往需要通过对

发表评论

电子邮件地址不会被公开。 必填项已用*标注

请补全下列算式: *

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据