问题出现的背景
字体管家的后台接口返回很慢,登录到相关机器,发现机器的负载高达28,30左右,定位为数据库的问题
定位的思路
查看数据库的慢查询语句,发现相关sdk统计的sql,执行了14s,猜测可能是相关慢查询语句阻碍了正常的查询,导致负载偏高,遂将相关的查询的入口暂时禁掉
禁掉后,重启数据库后,发现问题依旧,于是查看show proceslist;的内容,猜测,是否是由于某些大量频繁的sql的短查询导致整体的负载高。在show processlist;的过程中,发现大量的unthencated user;的请求链接
通过网上查询,发现,unthencation user 这种请求,可能是mysql的一个Bug,由于是针对需要进行dns反查的这种,于是,在mysql的配置文件中,增加skip-resolve-name选项,取消掉这种dns反查的设置。重启mysql后,发现现象依旧
通过观察,发现mysql初期的时候show processlist;还比较正常,但没多久,负载就非常高,猜测可能不是查询的问题导致的。然后,想起来这周将mysql的max-connection调成了5000,结合php使用mysql的方式,定位为该原因。将max-connection调整为1000,重启mysql后,问题解决
问题的结论
问题的主要的点,还是在于php使用mysql的方式。由于php没有像java的那种线程池,其对数据库的访问都是以短socket的方式来进行。由于将max-connection设置为5000,由于流量的增大,php就可以不断地获取到数据库的连接,从而进行相关数据的操作。但同时的访问很多,连接不断的增多,导致mysql所需要的资源也越多,这也解释了mysql导致系统负载偏高的原因。
关于最大连接数这个参数,由于php采用短socket的方式,连接->操作->释放,没有线程池的概念,所以,这块的最大连接数基本代表了1s内的数据库的请求并发数。但是,随着流量变大,请求的增多,请求所需要的连接数也会不断地增大。为了保证数据库操作的快速,迅捷,基本都会增加最大连接数这个参数,保证相关数据库操作能够快速地进行,而不是在那里等待上个数据库连接的释放。但是,增加连接数也带来了另一个问题,相关连接的资源消耗也是巨大的,包括cpu,内存,文件句柄数,网络等等。所以,最大连接数这部分也不宜太大。
问题出现的原因,就是最大连接数设置的太大,导致php请求,可以无限制地获取到数据库连接,请求的增多,导致瞬间增大了当前的数据库连接数,极大地增加了mysql的资源损耗,从而导致整体系统负载非常高。
问题的发散
以前的java由于存在连接池的概念,在应用里设置的获取的最大连接数也没超过200,对应日均2000的网站。那这块是否可以借鉴呢?
- php这种短socket的方式,固然可以快速地进行数据库的操作,但它的连接的管理方面,完全靠数据库端来进行,例如:最大连接数等。这块php有没有比较好的思路,借鉴类似java这种连接池的思路来管理这种数据库连接呢?