1、背景
因为业务需要,搭建了一个系统,系统主要由两部分组成,web页面和数据库。
mysql大概2万条数据,其中有一个字段是click_num点击次数,php页面会取点击次数最小的一条记录去进行操作,然后update一下click_num这个字段,让click_num=click_num+1。
2、问题
读取数据的客户端有1000个,大概40秒取一次任务,1秒并发25左右,在开始在mysql数据1万条以内的时候,数据库完全可以支撑,但是再加到了2万条数据的时候,网页加载数据的速度就非常慢了,查看CPU,发现服务器的CPU已经100%了。于是进行机器升级,升级到下面的配置
发现稍微好了一点点,但是CPU还是高达70%,load负载也非常大。
于是还想升级服务器,但是去查看阿里云,发现这个已经是顶配了,没有机会再升到更高的配置了,于是开始想着怎么从技术角度去优化。
3、发现问题
那么就开始查看问题,首先去判断了一下apache的http连接。
开始想了很多办法,以为是tcp连接太多出的问题,后面继续排查,发现瓶颈在数据库。
于是用
show processlist;
发现有很多查询卡主了,导致有400多个连接,连接总数一共才400,就导致后面的请求根本无法进来,重点的语句就这一个
SELECT * FROM down WHERE ENGINE='CLIENTBD' AND state =1 AND ownSign='gold' ORDER BY CLICK_NUM ASC,update_date ASC LIMIT 1
1
这个语句的意思,就是从数据库中查询出click_num最小的一条数据。而数据库的表中,2万条数据,其中click_num是有大量相同的最小值的,而且这个字段不断变化,因此也无法设置主键,因此全文排序导致该搜索异常缓慢。
4、异步化
其实技术方面去考虑,我每次只需要随机取click_num最小的一条记录,没有必要每次都进行一次检索排序,那么我是不是可以异步去处理?使用一个调度程序,5秒钟就把最小的100个值单独取出来,存到一个新的表中,然后页面在这个100个值的页面把数据取出来,然后再根据ID更新主表中的数据。
更新主表是使用主键ID,会非常快。
update down set click_num=click_num + 1,update_date = '".date("Y-m-d H:i:s",time())."' where id = ".$id
1
5、实施
调度程序采用tbscheduler,发现后面全部正常。
CPU
服务器负载
相对之前动不动就占用300%的情况,不知道优化了多少倍,服务器配置也能降低下来节省成本。
---------------------
作者:IT老蒋
来源:CSDN
原文:https://blog.csdn.net/itbuluoge/article/details/50902325
版权声明:本文为博主原创文章,转载请附上博文链接!