开发者社区> 吞吞吐吐的> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

LAMP网站性能优化记

简介:
+关注继续查看

先说说背景:一个LAMP在线测试网站,日均PV1万左右,比赛时一小时就好几万吧。目前数据库大约有30万条记录。服务器配置很高。近期出现性能问题,当访问量增大的时候,数据库服务器的压力非常大,mysql的内存占用率通常能到400%,这时候基本不能提供服务了,连网站页面都打不开。理论上说现在的数据量还不算大,访问量也不是很大,服务器的配置也很高,出现这种状况是不正常的。这个问题究结了很久,昨天终于找到问题的原因了,记录一下,以后遇到类似的问题可以有个参考。先看一张图片,这是glances监控软件的截图,可以看到红色的496.6就是mysql的CPU占用率

  之前遇到这个问题,只能重启mysql服务,但这只是暂时的,重启之后不到1分钟CPU占用率接着就上来了,不是长久之计。

  然后考虑修改数据库和apache的配置文件,加大缓存空间,但效果还是不明显。

  后来又考虑是不是路由器的问题,因为目前是两台服务器通过一个小路由器连起来,组成一个小局域网,一个放apache(压力很小),另一个服务器放数据库(压力很大),交换数据都要先经过路由器。于是开始怀疑路由器的性能问题,干脆直接用一根网线把两个服务器连起来(服务器有两个网卡)。这样两个服务器就能直接通信了。事实证明,这样还是不能解决数据库压力大的问题。

  接下来,还是各种纠结,想过各种方法,比如换nginx,换其他数据库,弄个数据库集群什么的,都比较麻烦,还需要修改php代码,比较费劲,关键是php这东西看着就恶心……  

  有一天,我发现了memcached,memcached是一个缓存系统,这么说吧,假如有一个查询语句,很费时间,如果没有缓存的话,每次刷新页面就要访问数据库查询一次,这样数据库压力就比较大。 如果有缓存就不一样了,如果要查询的数据在缓存中存在的话,就直接从缓存中取出来,这样就不用去数据库查询了,如果访问量大的话可以明显减少数据库的查询次数,当然也减轻了数据库的压力。先贴一段没有缓存的代码:

$list = $statics->getFirstTenList();

下面是加上缓存的代码:

$list = null;
if (!($list = $cache->get('top_ten_list'))) {
    $list = $statics->getFirstTenList();
    $cache->set('top_ten_list', $list, 7200);
}

没有缓存的代码,每次都要调用查询函数从数据库获取数据。下面的有缓存的就不一样了。当需要查询一个数据之前,首先看看缓存里面有没有,就是代码中$cache->get(),如果从缓存取得了,就不用执行那条查询数据库的语句了。如果缓存服务器没有,就要从数据库里面查询,查询以后,用$cache->set()方法就刚才的查询结果保存到缓存服务器,并设置这个缓存存在的时间,这里是7200秒,7200秒之后,这个缓存就失效了,就要从新更新。还有一点比较重要,就是要给每一个缓存取一个名字,不同的缓存名字不能相同,缓存服务器是根据缓存的名字来区分缓存,如果名字相同的话,从缓存取出来的数据就不是我们需要的数据。举个例子来说:有两个比赛,比赛的排名页面做一个缓存,如果两个缓存名字都叫ranklist,首先刷新一下第一个比赛的排名页面,那么第一个比赛的排名数据就存在缓存服务器了。如果这时再刷新一下第二个比赛的排名页面,因为ranklist在缓存中存在,直接就从缓存中取出来了,但是取出来的数据并不是我们需要的,这种问题还是比较小的。如果是不同类型的数据,那么网站就乱了。

  缓存是个好东西,然后打算通过大量增加缓存来减轻服务器的压力。但后来我发现,这样也不行。因为我们的网站是一个在线测评系统,是一个实时动态的系统,一个用户提交一个答案以后,想立即看到评判结果,当答案正确的时候,要立即更新排名信息。如果增加缓存的话,从缓存中取出来的信息就不是最新的,不能显示实时的排名等信息。这就好比你订了一张票,但是系统好久才提示你订票成功,中间的等待时间是最难熬的。还有一个原因也限制了缓存的使用,就是对于大量的页面,比如说服务器上有2000个题,一个题一个页面,如果一个页面一个缓存的话肯定会降低缓存的性能。但是对于一些数据,长时间变动不大,比如说总做题数的排名,就可以考虑增加一个缓存,可以设置半天或者一天的生存时间,也就是半天或者一天更新一次。

  由于大量缓存并不适用与我们这种实时性很高的系统,因此我并没有增加很多缓存。数据库压力还是那么大。还是没找到问题的根源。

  找到一本mysql性能优化的书,然后就开始研究,首先想到的还是加索引,后来用show index from table_name来查看,发现里面已经对常用的查询词加索引了,我甚至开始考虑是不是因为索引太多加重了数据库的压力?经过一些测试(删除某些索引),发现还是不行,看来通过增加索引已经不能很好得解决OJ问题。

  后来发现了一个语句,是 show processlist,这条命令的作用是显示哪些线程正在执行,执行了多长时间,还有一些其他信息,看截图:

上面的图片是在负载不是很大的时候截的,从上图我们能看到有两条sql查询语句已经执行了7秒了,还有一个正在往临时表拷贝数据的操作。真正比赛的时候比这个问题严重多了!有几个sql语句执行时间超过10秒,总的sql查询语句个数有200多个,当然大部分线程是被阻塞的。 在这里我们就能很明显看出来到底是哪一条sql语句在浪费时间,接下来,我们就要找到底这条sql查询语句是从哪发起的,从php源吗中找这条语句,如果一条一条找就费劲了,这里我们用强大的grep命令来帮助我们查找。

很明显,这几条语句就在一个文件里面,让我们打开这个文件看看,下面是其中的一个函数,包含上面的查询语句

这个函数是从哪调用的?再找

 看到了吧,这里有八条类似的语句,这8条语句的作用是什么?其中第一条的作用是从30万的表里找到今天提交的并且AC的题目总数,第二条就是统计今天的提交总数,下面几条分别是统计这周,这月,这年的AC和提交总数。显示提交状态的solution表中目前大约有30万条信息,并且随时都会更新,只要有人提交就会插入新数据并更新一些数据。在数据库理论里面将,统计和插入更新是互相冲突的,这里就需要加锁,当执行查询语句的时候,将这个表锁住,防止其他数据更新而影响查询结果。也就是说,当执行上面的查询语句时,数据库里面的其他语句就被阻塞了,就被迫去sleep。在提交高峰期,数据库里面被阻塞的语句能达到200多条甚至更多,mysql的CPU占用率达到能达到500%,肯定不能对外提供服务了!

  接下来,我们要找找到底是在哪个页面里面有这个统计,哪个页面调用了这个函数,(强大的grep)

当看到上面的结果的时候,我的心凌乱了~~靠,怎么回事?这个多页面都有这个统计,然后打开页面文件找找,找到了

(上图是我修改之后的查询结果,大部分都被我用//注释掉了,原来是没有注释的~)

在一个不起眼的边栏里,我看到了上面的一个统计。我调查了一些用户,你们注意过这个统计信息吗?你们关注过这个统计信息吗?答案和我想的一样,没有!谁都不关注那这个统计还有什么意义?不知道当初设计者怎么想到的这个功能。当初数据量小的时候没有这个问题,随着数据量增加,问题就暴露出来了。就是这8个数字,拖慢了整个网站的速度!

  接下来解决方案也很清晰了,两种方法:1.删除这个统计,2.给这个统计增加缓存。综合各方面的意见,我决定只在总的排名页面保留这个统计,当然是要增加缓存的,6个小时更新一次。其他页面全部去掉!

  解决这个问题之后,再试试网站的访问速度,那叫一个快啊!泪奔啊!纠结了这么久的性能问题终于解决啦!orz


博主ma6174对本博客文章(除转载的)享有版权,未经许可不得用于商业用途。转载请注明出处http://www.cnblogs.com/ma6174/

对文章有啥看法或建议,可以评论或发电子邮件到ma6174@163.com


本文转自ma6174博客园博客,原文链接:http://www.cnblogs.com/ma6174/archive/2012/12/16/2818666.html,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Web优化躬行记(5)——网站优化
  最近阅读了很多优秀的网站性能优化的文章,所以自己也想总结一些最近优化的手段和方法。   个人感觉性能优化的核心是:减少延迟,加速展现。   本文主要从产品设计、前端、后端和网络四个方面来诉说优化过程。
36 0
记一次提升18倍的性能优化
最近负责的一个自研的 Dubbo 注册中心经常收到 CPU 使用率的告警,于是进行了一波优化,效果还不错,于是打算分享下思考、优化过程,希望对大家有一些帮助。 自研 Dubbo 注册中心是个什么东西,我画个简图大家稍微感受一下就好,看不懂也没关系,不影响后续的理解。
44 0
不做外链 网站SEO优化还有戏吗
如果你在2019年仍然还在坚持做SEO,那么耳熟能详的“外链建设”仍然是我们SEO优化工作的重点。有些朋友会问,没有外链还能否做SEO呢?如果能做,那么为什么要花大量时间和人力去建设外链呢? 没有外链,还能做SEO吗?根据安邦运维的研究发现,没有外链我们有以下两种方法来操作。
770 0
网站前端和后台性能优化34
把组件打包进多部分文档中 Pack Components into a Multipart Document
1895 0
赣州网站建设一定要重视代码编写和后期优化
赣州网站建设过程对细节最为关注的两个步骤非代码的编写和后期的优化莫属,这两个过程,既有繁杂性,又有重要性,也是最能够体现网站质量的连个部门,一个要服务于本地电脑,一个要服务于搜索引擎,各司其职
1942 0
Hexo折腾记——性能优化篇
折腾Hexo的本来目的就是为了学习把性能优化到极致,由于水平有限,这里牵涉到的所谓的性能优化仅仅只是一些表面工夫,并不牵涉非常细节的前端性能。 另外,由于我朝特殊的网络环境,我使用的谷歌分析,以及Disqus 均会导致出现因时因地因运营商而异的发抽状况,故而所有速度测试均在排除这些干扰下进行的
13780 0
大型网站性能优化的通用方法(转)
1、HTML静态化 其实大家都知道,效率最高、消耗最小的就是纯静态化的html页面,所以我们尽可能使我们的网站上的页面采用静态页面来实现,这个最简单的方法其实也是最有效的方法。但是对于大量内容并且频繁更新的网站,我们无法全部手动去挨个实现,于是出现了我们常见的信息发布系统CMS,像我们常访问的各个门户站点的新闻频道,甚至他们的其他频道,都是通过信息发布系统来管理和实现的,信息发布系统可以实现最简单的信息录入自动生成静态页面,还能具备频道管理、权限管理、自动抓取等功能,对于一个大型网站来说,拥有一套高效、可管理的CMS是必不可少的。
1004 0
4849
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载