在你回答这个问题之前,我从来没有开发过任何流行到足以达到高服务器负载的东西。请把我当作(唉)一个刚刚登陆地球的外星人,尽管我知道PHP和一些优化技术。


我正在开发一个PHP工具,可以获得相当多的用户,如果它是正确的。然而,虽然我完全有能力开发程序,但当涉及到制作可以处理巨大流量的东西时,我几乎一无所知。所以这里有一些关于它的问题(也可以把这个问题变成一个资源线程)。

数据库

At the moment I plan to use the MySQLi features in PHP5. However how should I setup the databases in relation to users and content? Do I actually need multiple databases? At the moment everything's jumbled into one database - although I've been considering spreading user data to one, actual content to another and finally core site content (template masters etc.) to another. My reasoning behind this is that sending queries to different databases will ease up the load on them as one database = 3 load sources. Also would this still be effective if they were all on the same server?

缓存

我有一个用于构建页面和交换变量的模板系统。主模板存储在数据库中,每当一个模板被调用时,它的缓存副本(html文档)就会被调用。目前,我在这些模板中有两种类型的变量-静态变量和动态变量。静态变量通常是像页面名称,网站的名称-不经常改变的东西;动态变量是在每次页面加载时改变的东西。

我的问题是:

比如说我对不同的文章有评论。这是一个更好的解决方案:存储简单的注释模板,并在每次页面加载时呈现注释(来自DB调用),或者将注释页面的缓存副本存储为html页面——每次添加/编辑/删除注释时,页面都会被重新检索。

最后

有人有任何提示/指针运行一个高负载的PHP网站。我很确定这是一种可行的语言——Facebook和Yahoo!优先考虑——但有什么经验是我应该注意的吗?


当前回答

已经给出了很多很好的答案,但我想向您介绍另一种称为XCache的操作码缓存。它是由一个轻量级贡献者创建的。

此外,如果你将来可能需要负载平衡你的数据库服务器,MySQL代理可以很好地帮助你实现这一点。

这两种工具都可以很容易地插入到现有的应用程序中,因此可以在需要时进行优化,而不需要太多麻烦。

其他回答

我运营的网站每月有700万到800万的访问量。不是特别多,但足以让我们的服务器感受到负载。我们选择的解决方案很简单:数据库级的Memcache。如果数据库负载是您的主要问题,则此解决方案效果很好。

我们开始使用Memcache缓存最常用的整个对象和数据库结果。它确实起作用了,但它也引入了bug(如果我们更加小心的话,我们可能会避免其中一些bug)。

所以我们改变了我们的方法。我们构建了一个数据库包装器(使用与旧数据库完全相同的方法,因此很容易切换),然后我们将其子类化以提供memcached数据库访问方法。

现在,您所要做的就是决定查询是否可以使用缓存(可能已经过期)的结果。用户运行的大多数查询现在都直接从Memcache中获取。例外情况是更新和插入,这对于主网站来说只发生在日志记录中。这个相当简单的措施减少了大约80%的服务器负载。

无论如何,在PHP中缓存是非常简单的,即使没有像memcached这样的扩展/帮助包。

你所需要做的就是使用ob_start()创建一个输出缓冲区。

创建全局缓存函数。调用ob_start,将函数作为回调函数传递。在函数中,查找页面的缓存版本。如果存在,就把它送上,然后结束。

如果不存在,脚本将继续处理。当它到达匹配的ob_end()时,它将调用您指定的函数。这时,您只需要获取输出缓冲区的内容,将它们放到一个文件中,保存文件,然后结束。

添加一些过期/垃圾收集。

许多人没有意识到可以嵌套ob_start()/ob_end()调用。如果你已经在使用输出缓冲区来解析广告或者做语法高亮等等,你可以嵌套另一个ob_start/ob_end调用。

APC是绝对必须的。它不仅是一个伟大的缓存系统,而且从自动缓存的PHP文件中获得的好处是天赐良机。至于多数据库的想法,我认为在同一台服务器上使用不同的数据库不会有什么好处。它可能会在查询时提高一些速度,但我怀疑为确保三者同步而部署和维护代码所付出的努力是否值得。

我还强烈建议运行Xdebug来查找程序中的瓶颈。它使优化对我来说轻而易举。

首先,正如Knuth所说,“过早的优化是万恶之源”。如果你现在不需要处理这些问题,那就不要去做,先专注于交付一些正确工作的东西。也就是说,如果优化不能等待。

试着分析你的数据库查询,找出什么是慢的,什么是经常发生的,并从中提出一个优化策略。

我会研究Memcached,因为很多高负载站点都使用它来有效地缓存所有类型的内容,而且它的PHP对象接口非常好。

在服务器之间分割数据库并使用某种负载平衡技术(例如,在具有必要数据的冗余数据库中生成1到#之间的随机数—并使用该数字确定要连接到哪个数据库服务器)也是提高效率的一种极好的方法。

在过去,对于一些相当高的负载站点,这些方法都非常有效。希望这能帮助你开始:-)

我不敢相信居然没有人提到这个:模块化和抽象。如果您认为您的站点将不得不扩展到许多机器,那么您必须这样设计它!这意味着一些愚蠢的事情,比如不要假设数据库在本地主机上。它还意味着一些一开始会很麻烦的事情,比如编写数据库抽象层(像PDO,但要轻得多,因为它只做您需要它做的事情)。

这意味着在一个框架下工作。您将需要对代码进行分层,以便稍后通过重构数据抽象层(例如,通过告诉它某些对象位于不同的数据库中)来获得性能,并且代码不必知道或关心。

最后,要注意内存密集型操作,例如不必要的字符串复制。如果你能保持PHP的内存使用较低,那么你的web服务器就会得到更好的性能,当你采用负载平衡的解决方案时,这是可以扩展的。