在你回答这个问题之前,我从来没有开发过任何足以获得高服务器负载的东西。把我当作(感叹)一个刚刚降落在这个星球上的外星人,虽然知道了PHP和一些优化技术。
我正在开发一个 PHP 的工具,如果工作正常,可以获得相当多的用户。然而,虽然我完全有能力开发这个程序,但在制作可以处理巨大流量的东西方面,我几乎一无所知。所以这里有几个问题(随意将这个问题转化为资源线程)。
目前我打算在PHP5中使用MySQLi功能。但是,我应该如何设置与用户和内容相关的数据库?我实际上需要多个数据库吗?目前,所有内容都混杂在一个数据库中 - 尽管我一直在考虑将用户数据分散到一个数据库,将实际内容传播到另一个数据库,最后将核心网站内容(模板主人等)传播到另一个数据库。我的理由是,将查询发送到不同的数据库将减轻它们的负担,因为一个数据库= 3个负载源。如果它们都在同一台服务器上,它还会有效吗?
我有一个模板系统,用于构建页面和交换变量。主模板存储在数据库中,每次调用模板时,都会调用缓存副本(html文档)。目前我在这些模板中有两种类型的变量 - 静态变量和动态变量。静态变量通常是页面名称,站点名称 - 不经常更改的东西;动态变量是每次加载页面时都会发生变化的事情。
我的问题:
说我对不同的文章有评论。这是一个更好的解决方案:每次加载页面时存储简单的注释模板并呈现注释(来自数据库调用),或者将注释页面的缓存副本存储为html页面 - 每次添加/编辑/删除注释页面被重新访问。
有没有人有任何关于在PHP上运行高负载站点的提示/指针。我很确定这是一种可行的语言 - Facebook和Yahoo!给予它很大的优先权 - 但有任何经验值得我注意吗?
答案 0 :(得分:88)
没有两个网站是相似的。你真的需要一个像jmeter和基准测试这样的工具来查看你的问题点。您可以花费大量时间进行猜测和改进,但在衡量和比较更改之前,您不会看到实际结果。
例如,多年来,MySQL查询缓存是我们所有性能问题的解决方案。如果您的网站速度很慢,MySQL专家建议打开查询缓存。事实证明,如果你有很高的写入负载,缓存实际上是瘫痪的。如果你在没有测试的情况下打开它,你就永远不会知道。
不要忘记你从未完成过缩放。处理10req / s的站点将需要更改以支持1000req / s。如果你的运气足够需要支持10,000req / s,那么你的架构也可能看起来完全不同。
答案 1 :(得分:59)
我是一个拥有超过1500万用户的网站的首席开发人员。我们的扩展问题非常少,因为我们已经为它做了很早的计划并且经过精心设计。以下是我可以根据自己的经验提出的一些策略。
<强> SCHEMA 强> 首先,对您的模式进行非规范化。这意味着您应该选择拥有一个大表,而不是拥有多个关系表。通常,连接是浪费宝贵的数据库资源,因为进行多次准备和整理会烧毁磁盘I / O.尽可能避免使用它们。
这里的权衡是你将存储/提取冗余数据,但这是可以接受的,因为数据和笼内带宽非常便宜(更大的磁盘),而多个准备I / O的数量级要贵一些(更多服务器)。
<强>编制索引强> 确保您的查询至少使用一个索引。但请注意,如果您经常编写或更新,索引将花费您。有一些实验技巧可以避免这种情况。
您可以尝试添加未编入索引的其他列,这些列与索引的列并行运行。然后,您可以拥有一个脱机进程,将非索引列分批写入索引列。这样,当mySQL需要重新计算索引时,您可以更好地控制。
避免像瘟疫这样的计算查询。如果必须计算查询,请尝试在写入时执行一次。
<强> CACHING 强> 我强烈推荐Memcached。 PHP堆栈(Facebook)上最大的玩家已经证明了这一点并且非常灵活。这有两种方法,一种是在数据库层缓存,另一种是在业务逻辑层缓存。
DB层选项需要缓存从DB检索的查询结果。您可以使用md5()散列SQL查询,并在转到数据库之前将其用作查找键。这样做的好处是它很容易实现。缺点(取决于实现)是您失去了灵活性,因为您在缓存过期方面将所有缓存视为相同。
在我工作的商店中,我们使用业务层缓存,这意味着我们系统中的每个具体类都控制着自己的缓存模式和缓存超时。这对我们来说非常有效,但请注意,从DB检索的项目可能与缓存中的项目不同,因此您必须一起更新缓存和DB。
DATA SHARDING 复制只能让你到目前为止。比你预期的要早,你的写作将成为瓶颈。要进行补偿,请确保尽早支持数据分片。如果你不这样做,你可能会想要自己拍摄。
实施起来非常简单。基本上,您希望将密钥授权与数据存储分开。使用全局DB存储主键和群集ID之间的映射。您查询此映射以获取群集,然后查询群集以获取数据。你可以缓存这个查找操作的地狱,这将使它成为一个可以忽略不计的操作。
这样做的缺点是可能很难将来自多个分片的数据拼凑在一起。但是,你也可以设计自己的方式。
离线处理 如果用户不必,请不要让用户等待你的后端。构建一个作业队列并移动任何可以脱机的处理,并将其与用户的请求分开。
答案 2 :(得分:41)
我曾经在一些网站上工作过,这些网站每月都有数百万/次点击支持PHP&amp; MySQL的。以下是一些基础知识:
我建议阅读Building Scalable Websites,它是由Flickr工程师之一编写的,是一个很好的参考。
查看我关于可扩展性的博文,它有很多关于使用多种语言和平台进行扩展的演示文稿的链接: http://www.ryandoherty.net/2008/07/13/unicorns-and-scalability/
答案 3 :(得分:39)
Re:PDO / MySQLi / MySQLND
@ gary
你不能只说“不要使用MySQLi”,因为他们有不同的目标。 PDO几乎就像一个抽象层(虽然它实际上并不是这样),旨在使多个数据库产品易于使用,而MySQLi则专门用于MySQL连接。在将它与MySQLi进行比较的背景下,PDO是现代访问层是错误的,因为你的陈述意味着进展是mysql - &gt; mysqli - &gt; PDO并非如此。
MySQLi和PDO之间的选择很简单 - 如果您需要支持多个数据库产品,那么您可以使用PDO。如果您只是使用MySQL,那么您可以在PDO和MySQLi之间进行选择。
那你为什么选择MySQLi而不是PDO呢?见下文......
你对MySQLnd这是最新的MySQL核心语言级库是正确的,但它不是MySQLi的替代品。 MySQLi(与PDO一样)仍然是通过PHP代码与MySQL交互的方式。这两个都使用libmysql作为PHP代码背后的C客户端。问题是libmysql不在核心PHP引擎之外,而且是mysqlnd的用武之地,即它是一个本机驱动程序,它利用核心PHP内部来最大限度地提高效率,特别是在内存使用方面。
MySQL正在由MySQL自己开发,最近已经进入了RC测试的PHP 5.3分支,准备在今年晚些时候发布。然后,您将能够将MySQLnd与MySQLi一起使用......但不能与PDO一起使用。如果您不需要像PDO这样的抽象功能,这将使MySQLi a performance boost在许多领域(而不是全部)成为MySQL互动的最佳选择。那就是说,MySQLnd is now available in PHP 5.3用于PDO,因此你可以从ND到PDO中获得性能增强的优势,但是,PDO仍然是一个通用的数据库层,因此将是unlikely to be able to benefit as much from the enhancements in ND as MySQLi can。< / p>
Some useful benchmarks can be found here虽然它们来自2006年。您还需要了解this option之类的内容。
在决定使用MySQLi和PDO时,需要考虑很多因素。事实上,直到你得到高得多的请求数字并不重要,在这种情况下,使用专门为MySQL设计的扩展而不是抽象的东西并且碰巧提供MySQL驱动程序更有意义。
这不是一个简单的问题,因为每个都有优点和缺点。您需要阅读我提供的链接并提出自己的决定,然后进行测试并找出答案。我在过去的项目中使用过PDO,它是一个很好的扩展,但我对纯性能的选择是MySQLi,编译了新的MySQLND选项(当PHP 5.3发布时)。
答案 4 :(得分:23)
常规强>
<强>代码强>
<强>数据库强>
<强>缓存强>
<强>杂强>
答案 5 :(得分:9)
首先,正如我认为Knuth所说,“过早优化是所有邪恶的根源”。如果您现在不必处理这些问题,那么请不要专注于首先提供正常工作的东西。话虽如此,如果优化不能等待。
尝试分析您的数据库查询,弄清楚什么是缓慢的,发生了什么,并从中提出优化策略。
我会调查Memcached因为它是许多较高负载站点用于高效缓存所有类型内容的东西,而且它的PHP对象接口非常好。
在服务器之间拆分数据库并使用某种负载平衡技术(例如,在1和#冗余数据库之间生成一个带有必要数据的随机数 - 并使用该数字来确定要连接到哪个数据库服务器)也可以是一个很好的选择提高效率的方法。
对于一些相当高负荷的网站来说,这些都在过去都很顺利。希望这有助于您入门: - )
答案 6 :(得分:9)
APC是绝对必须的。它不仅适用于一个出色的缓存系统,而且自动缓存的PHP文件的收益也是天赐之物。至于多数据库的想法,我认为你不会在同一台服务器上拥有不同的数据库。它可能会在查询时间内为您带来一些速度提升,但我怀疑在确保它们同步时为部署和维护所有三个代码所需的工作量是值得的。
我还强烈建议您运行Xdebug来查找程序中的瓶颈。它使我的优化变得轻而易举。
答案 7 :(得分:6)
使用Xdebug(如推荐的tj9991)对您的应用进行分析肯定是必须的。盲目地优化事物并没有多大意义。 Xdebug将帮助您找到代码中的真正瓶颈,这样您就可以明智地花费优化时间并修复实际导致缓慢下降的代码块。
如果你正在使用Apache,那么可以帮助测试的另一个实用程序是Siege。它可以帮助您预测服务器和应用程序如何通过真正实现其高速负载来应对高负载。
任何类型的PHP操作码缓存(如APC或许多其他操作系统)都会有很多帮助。
答案 8 :(得分:6)
对于它的价值,即使没有像memcached这样的扩展/帮助程序包,缓存在PHP中也是简单的。
您需要做的就是使用ob_start()
创建输出缓冲区。
创建全局缓存功能。调用ob_start
,将该函数作为回调传递。在该函数中,查找页面的缓存版本。如果存在,请服务并结束。
如果它不存在,脚本将继续处理。当它到达匹配的ob_end()时,它将调用你指定的函数。那时,您只需获取输出缓冲区的内容,将其放入文件中,保存文件,然后结束。
添加一些到期/垃圾回收。
很多人都没有意识到你可以嵌套ob_start()
/ ob_end()
来电。因此,如果您已经使用输出缓冲区来解析广告或进行语法突出显示等等,您可以嵌套另一个ob_start/ob_end
调用。
答案 9 :(得分:6)
我运营的网站每月有7到8百万的网页浏览量。不是很多,但足以让我们的服务器感受到负载。我们选择的解决方案很简单:数据库级别的Memcache。如果数据库负载是您的主要问题,此解决方案很有效。
我们开始使用Memcache来缓存整个对象和最常用的数据库结果。它确实有效,但它也引入了错误(如果我们更加小心的话,我们可能已经避免了一些错误)。
所以我们改变了方法。我们构建了一个数据库包装器(使用与旧数据库完全相同的方法,因此很容易切换),然后我们将其子类化以提供memcached数据库访问方法。
现在您要做的就是确定查询是否可以使用缓存(可能是过时的)结果。现在,用户运行的大多数查询都是直接从Memcache中获取的。例外是更新和插入,主网站只会因为日志记录而发生。这个相当简单的措施将我们的服务器负载减少了大约80%。
答案 10 :(得分:5)
感谢有关PHP缓存扩展的建议 - 您能否解释一个使用另一个的原因?我通过IRC听说过有关memcached的好消息,但从未听说过APC - 你对它们的看法是什么?我假设使用多个缓存系统非常有效。
实际上,many do use APC and memcached together ......
答案 11 :(得分:4)
看起来像I was wrong。 MySQLi仍在开发中。但根据文章,PDO_MySQL现在由MySQL团队贡献。来自文章:
MySQL改进的扩展 - mysqli - 是旗舰。它支持MySQL服务器的所有功能,包括 Charsets,Prepared Statements and 存储过程。司机提供了一个 hybrid API:你可以使用一个程序 或面向对象的编程风格 根据您的喜好。 mysqli来了 PHP 5及以上版本。注意结束 PHP 4的生活是2008-08-08。
PHP数据对象(PDO)是一个 数据库访问抽象层。 PDO 允许您使用相同的API调用 用于各种数据库。 PDO没有 提供任何程度的SQL抽象。 PDO_MYSQL是PDO的MySQL驱动程序。 PDO_MYSQL自带PHP 5.自PHP起 5.3 MySQL开发人员积极参与其中。 PDO的好处是 统一的API是以这个价格来的 例如,MySQL的特定功能 多个陈述,并不完整 通过统一的API支持。
请停止使用第一个MySQL PHP发布的驱动程序: 分机/ MySQL的。自推出以来 MySQL改进的扩展 - mysqli - 2004年使用PHP 5,没有理由继续使用最老的驱动程序 周围。 ext / mysql不支持 Charsets,Prepared Statements and 存储过程。它仅限于 MySQL 4.0的功能集。注意 MySQL的扩展支持 4.0结束于2008-12-31。不要限制自己的功能集 旧软件!升级到mysqli,请参阅 还有Converting_to_MySQLi。 mysql在 从我们的角度来看,仅维护模式 观点。
对我而言,这篇文章似乎偏向于MySQLi。我想我偏向于PDO。 我非常喜欢MySQLi上的PDO。这对我来说很直接。 API与我编写的其他语言更接近.OO数据库接口似乎工作得更好。
我没有遇到过PDO无法提供的任何特定MySQL功能。如果我这样做,我会感到惊讶。
答案 12 :(得分:3)
PDO也非常慢,其API非常复杂。如果可移植性不是一个问题,他们的理智思想中没有人应该使用它。让我们面对现实吧,99%的网络应用都没有。你只需坚持使用MySQL或PostrgreSQL,或者你正在使用的任何东西。
至于PHP问题以及需要考虑的因素。我认为过早优化是万恶之源。 ;)首先完成您的应用程序,尝试在编程时保持清洁,做一些文档并编写单元测试。有了上述所有内容,您将无需在时机成熟时重构代码。但首先你要完成并推出它以了解人们对它的反应。
答案 13 :(得分:2)
当然pdo很好,但has been some有关它的性能与mysql和mysqli的争议,虽然现在似乎已经修复了。
如果你设想可移植性,你应该使用pdo,但如果没有,你应该使用mysqli。它有一个OO接口,预处理语句,以及pdo提供的大部分内容(除了,便携性)。
另外,如果确实需要性能,请准备PHP 5.3中的(本机mysql)MysqLnd驱动程序,它将与php更紧密地集成,具有更好的性能和更高的内存使用率(以及性能统计数据)调谐)。
如果您拥有群集服务器(以及类似YouTube的加载),Memcache会很好,但我也会首先尝试APC。
答案 14 :(得分:2)
已经给出了很多好的答案,但我想指出一个名为XCache的备用操作码缓存。它是由一个轻微的贡献者创建的。
此外,如果您将来可能需要对数据库服务器进行负载平衡,MySQL Proxy可以帮助您实现此目的。
这两个工具都应该很容易插入现有应用程序,因此可以在需要时进行优化,而不会有太多麻烦。
答案 15 :(得分:2)
第一个问题是你真正期望它有多大?您计划投资基础设施的程度是多少?既然你觉得有必要在这里提出这个问题,我猜你希望在预算有限的情况下从小做起。
如果网站不可用,则性能无关紧要。而对于可用性,您需要水平扩展。你可以理智地逃脱的最小值是2台服务器,它们都运行apache,php和mysql。将一个DBMS设置为另一个DBMS。执行主服务器上的所有写操作以及本地数据库上的所有读操作(无论是什么) - 除非由于某种原因您需要读回刚刚读取的数据(使用主服务器)。确保你有适当的机器来自动提升奴隶并围住主人。使用循环DNS作为Web服务器地址,以便为从属节点提供更多的亲和力。
在这个阶段将数据分区到不同的数据库节点是一个非常糟糕的主意 - 但是您可能需要考虑将它分割到同一服务器上的不同数据库中(当您超越Facebook时,这将促进跨节点的分区)。
确保您拥有适当的监控和数据分析工具来衡量您的网站性能并确定瓶颈。通过编写更好的SQL /修复数据库模式可以解决大多数性能问题。
将模板缓存保留在数据库上是一个愚蠢的想法 - 数据库应该是结构化数据的中央公共存储库。将模板缓存保留在Web服务器的本地文件系统上 - 它将更快地提供,并且不会减慢数据库访问速度。
请使用操作码缓存。
花大量时间研究您的网站及其日志,以了解其进展如此缓慢的原因。
尽可能多地将缓存推送到客户端。
使用mod_gzip压缩所有内容。
下进行。
答案 16 :(得分:2)
我的第一条建议是考虑这个问题并在设计网站时牢记这一点,但不要过分。通常很难预测新网站的成功与否,我会更好地花时间提早完成并稍后优化。
一般情况下,简单快速。 模板让你失望。数据库减慢了你的速度。复杂的库让你失望。将模板分层,从数据库中检索它们并在复杂的库中解析它们 - &gt;时间延迟相互增加。
让基本网站启动并运行执行测试,以告诉您在哪里花费精力。很难看到目标位置。通常为了加快速度,你必须解开代码的复杂性,这会使代码变得更大,更难维护,所以你只想在必要时进行。
根据我的经验,建立数据库连接相对昂贵。如果您可以使用它,请不要连接到流量最大的页面上的一般访问者的数据库,例如站点的首页。创建多个数据库连接是疯狂的,几乎没有什么好处。
答案 17 :(得分:1)
我不认为自己很快会从MySQL切换 - 所以我想我不需要PDO的抽象功能。感谢DavidM的那些文章,他们给了我很多帮助。
答案 18 :(得分:1)
查看mod_cache,Apache Web服务器的输出缓存,类似于ASP.NET中的输出缓存。
是的,我可以看到它仍然是实验性的,但有一天它将是最终的。
答案 19 :(得分:1)
我无法相信没有人已经提到这一点:模块化和抽象。如果您认为您的网站将不得不扩展到许多计算机,那么您必须设计它以便它可以!这意味着愚蠢的事情就是不要假设数据库在localhost上。它也意味着一开始会很烦人的事情,比如写一个数据库抽象层(比如PDO,但更轻,因为它只做你需要它做的事情)。
这意味着像使用框架一样。您将需要代码层,以便稍后通过重构数据抽象层来获得性能,例如,通过教导它将某些对象放在不同的数据库中 - 并且代码不必知道或照顾。
最后,请注意内存密集型操作,例如,不必要的字符串复制。如果你可以减少PHP的内存使用量,那么你将从你的网络服务器中获得更多的性能,当你进入负载均衡的解决方案时,这将会扩展。
答案 20 :(得分:1)
@ Gary
不要使用MySQLi - PDO是'现代'OO数据库访问层。要使用的最重要的功能是查询中的占位符。它也很聪明,可以为您使用服务器端准备和其他优化。
我现在正在讨论PDO,看起来你是对的 - 不过我知道MySQL正在开发PHP的MySQLd扩展 - 我想要成功MySQL或MySQLi - 你怎么看?
感谢有关PHP缓存扩展的建议 - 您能否解释一个使用另一个的原因?我通过IRC听说过有关memcached的好消息,但从未听说过APC - 你对它们的看法是什么?我假设使用多个缓存系统非常有效。
我一定会整理一些剖析测试人员 - 非常感谢您对这些测试人员的建议。
答案 21 :(得分:1)
如果您正在处理大量数据,并且缓存没有削减它,请查看Sphinx。我们使用SphinxSearch获得了很好的结果,不仅可以用于更好的文本搜索,还可以在处理更大的表时作为MySQL的数据检索替代品。如果你使用SphinxSE(MySQL插件),它超过了我们从缓存中多次获得的性能提升,并且应用程序实现是一个难题。
答案 22 :(得分:1)
有关缓存的要点是正确的;它是构建高效应用程序中最不复杂和最重要的部分。我想补充一点,虽然memcached很棒,但如果您的应用程序位于单个服务器上,APC的速度要快5倍。
MySQL性能博客上的“缓存性能比较”帖子有一些有趣的基准 - http://www.mysqlperformanceblog.com/2006/08/09/cache-performance-comparison/。