在你回答这个问题之前,我从来没有开发过任何流行到足以达到高服务器负载的东西。请把我当作(唉)一个刚刚登陆地球的外星人,尽管我知道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!优先考虑——但有什么经验是我应该注意的吗?
首先,正如Knuth所说,“过早的优化是万恶之源”。如果你现在不需要处理这些问题,那就不要去做,先专注于交付一些正确工作的东西。也就是说,如果优化不能等待。
试着分析你的数据库查询,找出什么是慢的,什么是经常发生的,并从中提出一个优化策略。
我会研究Memcached,因为很多高负载站点都使用它来有效地缓存所有类型的内容,而且它的PHP对象接口非常好。
在服务器之间分割数据库并使用某种负载平衡技术(例如,在具有必要数据的冗余数据库中生成1到#之间的随机数—并使用该数字确定要连接到哪个数据库服务器)也是提高效率的一种极好的方法。
在过去,对于一些相当高的负载站点,这些方法都非常有效。希望这能帮助你开始:-)
首先,正如Knuth所说,“过早的优化是万恶之源”。如果你现在不需要处理这些问题,那就不要去做,先专注于交付一些正确工作的东西。也就是说,如果优化不能等待。
试着分析你的数据库查询,找出什么是慢的,什么是经常发生的,并从中提出一个优化策略。
我会研究Memcached,因为很多高负载站点都使用它来有效地缓存所有类型的内容,而且它的PHP对象接口非常好。
在服务器之间分割数据库并使用某种负载平衡技术(例如,在具有必要数据的冗余数据库中生成1到#之间的随机数—并使用该数字确定要连接到哪个数据库服务器)也是提高效率的一种极好的方法。
在过去,对于一些相当高的负载站点,这些方法都非常有效。希望这能帮助你开始:-)
一般
在开始看到真实世界的负载之前,不要尝试优化。你可能猜对了,但如果你猜错了,那你就是在浪费时间。
使用jmeter、xdebug或其他工具对站点进行基准测试。
如果加载开始成为一个问题,对象或数据缓存都可能涉及到,所以通常阅读缓存选项(memcached, MySQL缓存选项)
Code
对代码进行分析,以便了解瓶颈在哪里,以及它是在代码中还是在数据库中
数据库
Use MYSQLi if portability to other databases is not vital, PDO otherwise
If benchmarks reveal the database is the issue, check the queries before you start caching. Use EXPLAIN to see where your queries are slowing down.
After the queries are optimized and the database is cached in some way, you may want to use multiple databases. Either replicating to multiple servers or sharding (splitting the data over multiple databases/servers) may be appropriate, depending on the data, the queries, and the kind of read/write behavior.
缓存
Plenty of writing has been done on caching code, objects, and data. Look up articles on APC, Zend Optimizer, memcached, QuickCache, JPCache. Do some of this before you really need to, and you'll be less concerned about starting off unoptimized.
APC and Zend Optimizer are opcode caches, they speed up PHP code by avoiding reparsing and recompilation of code. Generally simple to install, worth doing early.
Memcached is a generic cache, that you can use to cache queries, PHP functions or objects, or entire pages. Code must be specifically written to use it, which can be an involved process if there are no central points to handle creation, update and deletion of cached objects.
QuickCache and JPCache are file caches, otherwise similar to Memcached. The basic concept is simple, but also requires code and is easier with central points of creation, update and deletion.
杂项
考虑高负载的替代web服务器。像lighthttp和nginx这样的服务器可以用比Apache少得多的内存处理大量流量,如果你可以牺牲Apache的强大功能和灵活性(或者如果你不需要这些东西,通常情况下,你不需要)。
请记住,现在的硬件非常便宜,所以一定要花费精力来优化一大块代码,而不是“让我们购买一个巨型服务器”。
考虑将“MySQL”和“scaling”标签添加到这个问题中
我运营的网站每月有700万到800万的访问量。不是特别多,但足以让我们的服务器感受到负载。我们选择的解决方案很简单:数据库级的Memcache。如果数据库负载是您的主要问题,则此解决方案效果很好。
我们开始使用Memcache缓存最常用的整个对象和数据库结果。它确实起作用了,但它也引入了bug(如果我们更加小心的话,我们可能会避免其中一些bug)。
所以我们改变了我们的方法。我们构建了一个数据库包装器(使用与旧数据库完全相同的方法,因此很容易切换),然后我们将其子类化以提供memcached数据库访问方法。
现在,您所要做的就是决定查询是否可以使用缓存(可能已经过期)的结果。用户运行的大多数查询现在都直接从Memcache中获取。例外情况是更新和插入,这对于主网站来说只发生在日志记录中。这个相当简单的措施减少了大约80%的服务器负载。
看来我错了。MySQLi仍在开发中。但是根据这篇文章,PDO_MySQL现在由MySQL团队贡献。摘自文章:
The MySQL Improved Extension - mysqli
- is the flagship. It supports all features of the MySQL Server including
Charsets, Prepared Statements and
Stored Procedures. The driver offers a
hybrid API: you can use a procedural
or object-oriented programming style
based on your preference. mysqli comes
with PHP 5 and up. Note that the End
of life for PHP 4 is 2008-08-08.
The PHP Data Objects (PDO) are a
database access abstraction layer. PDO
allows you to use the same API calls
for various databases. PDO does not
offer any degree of SQL abstraction.
PDO_MYSQL is a MySQL driver for PDO.
PDO_MYSQL comes with PHP 5. As of PHP
5.3 MySQL developers actively contribute to it. The PDO benefit of a
unified API comes at the price that
MySQL specific features, for example
multiple statements, are not fully
supported through the unified API.
Please stop using the first MySQL
driver for PHP ever published:
ext/mysql. Since the introduction of
the MySQL Improved Extension - mysqli
- in 2004 with PHP 5 there is no reason to still use the oldest driver
around. ext/mysql does not support
Charsets, Prepared Statements and
Stored Procedures. It is limited to
the feature set of MySQL 4.0. Note
that the Extended Support for MySQL
4.0 ends at 2008-12-31. Don't limit yourself to the feature set of such
old software! Upgrade to mysqli, see
also Converting_to_MySQLi. mysql is in
maintenance only mode from our point
of view.
对我来说,这篇文章似乎偏向MySQLi。我想我偏向于PDO。
我真的很喜欢PDO胜过MySQLi。这对我来说很简单。这个API更接近于我编写的其他语言。OO数据库接口似乎工作得更好。
我还没有遇到过任何PDO无法提供的MySQL特性。如果有的话,我才会惊讶呢。