Ros*_*oss 240 php performance high-load
在回答这个问题之前,我从来没有开发出任何足以获得高服务器负载的东西.把我视为(感叹)一个刚刚降落在这个星球上的外星人,虽然他知道PHP和一些优化技术.
我正在开发一个PHP工具,可以获得相当多的用户,如果它正确的话.然而,虽然我完全有能力开发这个程序,但在制作可以处理巨大流量的东西方面,我几乎一无所知.所以这里有几个问题(随意将这个问题转化为资源线程).
目前我打算在PHP5中使用MySQLi功能.但是,我应该如何设置与用户和内容相关的数据库?我真的需要多个数据库吗?目前,所有内容都混杂在一个数据库中 - 尽管我一直在考虑将用户数据分散到一个数据库,将实际内容传播到另一个数据库,最后将核心网站内容(模板主人等)传播到另一个数据库.我的理由是,将查询发送到不同的数据库将减轻它们的负担,因为一个数据库= 3个负载源.如果它们都在同一台服务器上,它还会有效吗?
我有一个模板系统,用于构建页面和交换变量.主模板存储在数据库中,每次调用模板时,都会调用缓存副本(html文档).目前,我在这些模板中有两种类型的变量 - 静态变量和动态变量.静态变量通常是页面名称,站点名称 - 不经常更改的东西; 动态变量是每个页面加载时发生变化的事物.
我的问题是:
说我对不同的文章有评论.这是一个更好的解决方案:存储简单的评论模板,并呈现评论(从DB调用)每个页面加载时间或存储评论页面的缓存副本为HTML页面 - 每次添加注释时间/编辑/删除页面被记录下来.
有没有人有任何关于在PHP上运行高负载站点的提示/指针.我很确定这是一种可行的语言 - Facebook和Yahoo! 给它优先考虑 - 但是有什么经验值得我注意吗?
Gar*_*son 88
没有两个网站是相似的.你真的需要得到像jmeter和基准测试这样的工具来查看你的问题所在.您可以花费大量时间进行猜测和改进,但在衡量和比较更改之前,您不会看到实际结果.
例如,多年来,MySQL查询缓存是解决我们所有性能问题的方法.如果您的网站速度很慢,MySQL专家建议打开查询缓存.事实证明,如果你有很高的写入负载,缓存实际上是瘫痪的.如果你在没有测试的情况下打开它,你就永远不会知道.
不要忘记你从未完成过缩放.处理10req/s的站点将需要更改以支持1000req/s.如果你的运气足够需要支持10,000req/s,你的架构可能看起来也会完全不同.
the*_*art 59
我是一个拥有超过1500万用户的网站的首席开发人员.我们的扩展问题非常少,因为我们已经为它做了很早的计划并且经过精心设计.以下是我可以根据自己的经验提出的一些策略.
SCHEMA 首先,对您的模式进行非规范化.这意味着您应该选择拥有一个大表,而不是拥有多个关系表.通常,连接是浪费宝贵的数据库资源,因为进行多次准备和整理会烧毁磁盘I/O. 尽可能避免使用它们.
这里的权衡是您将存储/提取冗余数据,但这是可以接受的,因为数据和笼内带宽非常便宜(更大的磁盘),而多个准备I/O的数量级更高(更多服务器) .
索引 确保您的查询至少使用一个索引.但请注意,如果您经常编写或更新,索引将花费您.有一些实验技巧可以避免这种情况.
您可以尝试添加未编制索引的其他列,这些列与索引的列并行运行.然后,您可以拥有一个脱机进程,将非索引列分批写入索引列.这样,当mySQL需要重新计算索引时,您可以更好地控制.
避免像瘟疫这样的计算查询.如果必须计算查询,请尝试在写入时执行一次.
CACHING 我强烈推荐Memcached.PHP堆栈(Facebook)上最大的玩家已经证明了这一点并且非常灵活.有两种方法可以做到这一点,一种是在数据库层中进行缓存,另一种是在业务逻辑层中进行缓存.
DB层选项需要缓存从DB检索的查询的结果.您可以使用md5()散列SQL查询,并在转到数据库之前将其用作查找键.这样做的好处是它很容易实现.缺点(取决于实现)是您失去了灵活性,因为您在缓存过期方面将所有缓存视为相同.
在我工作的商店中,我们使用业务层缓存,这意味着我们系统中的每个具体类都控制着自己的缓存模式和缓存超时.这对我们来说非常好用,但要注意从DB检索的项目可能与缓存中的项目不同,因此您必须一起更新缓存和DB.
数据保护 复制只能让你到目前为止.比你预期的要早,你的写作将成为瓶颈.要进行补偿,请确保尽早支持数据分片.如果你不这样做,你可能会想要自己拍摄.
实现起来非常简单.基本上,您希望将密钥授权与数据存储分开.使用全局DB存储主键和群集ID之间的映射.您查询此映射以获取群集,然后查询群集以获取数据.你可以缓存这个查找操作的地狱,这将使它成为一个可以忽略不计的操作.
这样做的缺点是可能很难将来自多个分片的数据拼凑在一起.但是,你也可以设计自己的方式.
离线处理 如果用户不必,请不要让用户等待你的后端.构建作业队列并移动可以脱机的任何处理,将其与用户的请求分开.
Rya*_*rty 41
我曾经在一些网站上工作过,这些网站每月都有数百万/次点击支持PHP和MySQL.以下是一些基础知识:
我建议阅读Building Scalable Websites,它是由Flickr工程师之一编写的,是一个很好的参考.
查看我关于可扩展性的博客文章,它有很多关于使用多种语言和平台进行扩展的演示文稿的链接:http: //www.ryandoherty.net/2008/07/13/unicorns-and-scalability/
Dav*_*idM 39
Re:PDO/MySQLi/MySQLND
@ gary
你不能只说"不要使用MySQLi",因为他们有不同的目标.PDO几乎就像一个抽象层(虽然它实际上并不是这样),旨在使多个数据库产品易于使用,而MySQLi则专门用于MySQL连接.说PDO是将它与MySQLi进行比较的上下文中的现代访问层是错误的,因为你的语句意味着进展是mysql - > mysqli - > PDO,但事实并非如此.
MySQLi和PDO之间的选择很简单 - 如果您需要支持多个数据库产品,那么您可以使用PDO.如果您只是使用MySQL,那么您可以在PDO和MySQLi之间进行选择.
那你为什么选择MySQLi而不是PDO呢?见下文...
你对MySQLnd这是最新的MySQL核心语言级库是正确的,但它不是MySQLi的替代品.MySQLi(与PDO一样)仍然是通过PHP代码与MySQL交互的方式.这两个都使用libmysql作为PHP代码背后的C客户端.问题是libmysql不在核心PHP引擎之外,而是mysqlnd的用武之地,即它是一个本机驱动程序,它利用核心PHP内部来最大限度地提高效率,特别是在内存使用方面.
MySQLnd由MySQL自己开发,最近已经进入了用于RC测试的PHP 5.3分支,准备在今年晚些时候发布.然后,您将能够将MySQLnd与MySQLi一起使用......但不能与PDO一起使用.这将使MySQLi 在许多领域(并非所有领域)都有性能提升,并且如果您不需要像PDO这样的抽象功能,它将使其成为MySQL交互的最佳选择.
也就是说,MySQLnd 现在可以在PHP 5.3中用于PDO,因此您可以获得从ND到PDO的性能增强的优势,但是,PDO仍然是一个通用的数据库层,因此不太可能从作为MySQLi的ND的增强功能可以.
虽然它们来自2006年,但可以在这里找到一些有用的基准测试.您还需要了解此选项之类的内容.
在MySQLi和PDO之间进行决策时需要考虑很多因素.事实上,直到你得到高得多的请求数字并不重要,在这种情况下,使用专门为MySQL设计的扩展而不是抽象的东西并且碰巧提供MySQL驱动程序更有意义.
这不是一个简单的问题,因为每个都有优点和缺点.您需要阅读我提供的链接并提出自己的决定,然后进行测试并找出答案.我在过去的项目中使用过PDO,它是一个很好的扩展,但我对纯性能的选择是MySQLi,编译了新的MySQLND选项(当PHP 5.3发布时).
Pau*_*oll 23
一般
码
数据库
高速缓存
杂
首先,正如我认为Knuth所说,"过早优化是万恶之源".如果您现在不必处理这些问题,那么请不要专注于首先提供正常工作的东西.话虽如此,如果优化不能等待.
尝试分析您的数据库查询,找出什么是缓慢的,以及发生了什么,并从中提出优化策略.
我会调查Memcached,因为它是许多较高负载站点用于有效缓存所有类型的内容的东西,并且它的PHP对象接口非常好.
在服务器之间拆分数据库并使用某种负载平衡技术(例如,在1和#冗余数据库之间生成具有必要数据的随机数 - 并使用该数字来确定要连接到哪个数据库服务器)也是一种很好的增加方式效率.
对于一些相当高负荷的站点,这些在过去都很好.希望这有助于您入门:-)
我运营的网站每月有7-8百万的页面浏览量.不是很多,但足以让我们的服务器感受到负载.我们选择的解决方案很简单:数据库级别的Memcache.如果数据库负载是您的主要问题,此解决方案很有效.
我们开始使用Memcache来缓存整个对象和最常用的数据库结果.它确实有效,但它也引入了错误(如果我们更加小心的话,我们可能已经避免了一些错误).
所以我们改变了方法.我们构建了一个数据库包装器(使用与旧数据库完全相同的方法,因此很容易切换),然后我们将其子类化以提供memcached数据库访问方法.
现在,您所要做的就是确定查询是否可以使用缓存(可能是过时的)结果.现在,用户运行的大多数查询都是直接从Memcache中获取的.例外是更新和插入,主网站只会因为日志记录而发生.这个相当简单的措施将我们的服务器负载减少了大约80%.
小智 6
对于它的价值,即使没有像memcached这样的扩展/帮助程序包,缓存也是PHP中的DIRT SIMPLE.
您需要做的就是使用创建输出缓冲区ob_start().
创建全局缓存功能.调用ob_start,将函数作为回调传递.在该函数中,查找页面的缓存版本.如果存在,请服务并结束.
如果它不存在,脚本将继续处理.当它到达匹配的ob_end()时,它将调用您指定的函数.那时,您只需获取输出缓冲区的内容,将其放入文件中,保存文件,然后结束.
添加一些到期/垃圾回收.
许多人没有意识到你可以嵌套ob_start()/ ob_end()打电话.因此,如果您已经使用输出缓冲区来解析广告或进行语法突出显示等等,您可以嵌套另一个ob_start/ob_end调用.
感谢您对PHP缓存扩展的建议 - 您能解释一个使用另一个的原因吗?我通过IRC听说过有关memcached的好消息,但从未听说过APC - 你对它们的看法是什么?我假设使用多个缓存系统非常有效.
实际上,很多人一起使用APC和memcached ......