加入收藏 | 设为首页 | 会员中心 | 我要投稿 站长网 (https://www.0951zz.com/)- 云通信、基础存储、云上网络、机器学习、视觉智能!
当前位置: 首页 > 运营中心 > 交互 > 正文

运营中心PHP卡顿?3步优化立竿见影

发布时间:2026-10-14 08:14:21 所属栏目:交互 来源:DaWei
导读:  凌晨三点半,手机在枕头底下震得跟电钻似的——运营中心PHP卡顿的告警炸了。我原以为又是哪个开发偷偷改SQL没走索引,结果爬起来一看,好几台机器的CPU都顶到90%,慢查询日志里全是全表扫描的记录。开发老张在群里喊“绝

  凌晨三点半,手机在枕头底下震得跟电钻似的——运营中心PHP卡顿的告警炸了。我原以为又是哪个开发偷偷改SQL没走索引,结果爬起来一看,好几台机器的CPU都顶到90%,慢查询日志里全是全表扫描的记录。开发老张在群里喊“绝对不是我写的代码”,可监控里明明白白显示,这波流量是平时的两倍,但代码根本没动过。

  第一反应是查PHP-FPM的配置。我翻出那台主机的php.ini,发现pm.max_children直接设成了200——这数儿是三年前刚上线时随便填的,当时机器才8核16G内存,现在早就扩容到16核32G了,可配置没跟着改。我原以为调大pm.max_children能扛更多并发,结果反而把内存吃爆了——每个PHP进程占200M,200个进程直接40G内存,机器总共才32G,剩下的全靠swap,能不卡吗?我直接改成了“pm = dynamic”加“pm.max_spare_servers = 30”,重启服务后,CPU从90%掉到40%,但慢查询还在,说明根儿不在PHP这儿。

  这时候开发老李的电话打进来,说他在测试环境复现了问题,但“测试环境没卡啊”。我骂他:“测试环境就三台机器,流量是线上的百分之一,能卡才有鬼!”他支支吾吾说:“那…那可能是MySQL的问题?”我挂电话前补了句:“你丫要是再敢说‘可能是’,我今晚就把你写的存储过程全改成全表扫描!”

  第二刀砍向MySQL。慢查询日志里有个SQL特别扎眼:SELECT FROM orders WHERE user_id IN (1,2,3…200)——这IN列表直接塞了200个ID,而且user_id字段没索引!我原以为开发不会犯这种低级错误,结果一查代码,发现是某个接口为了“兼容旧数据”,故意没加索引。我直接给user_id加了个普通索引,重启MySQL后,这条SQL的执行时间从3秒掉到0.02秒,但其他慢查询还在——比如有个GROUP BY user_id的查询,居然用了临时表,因为user_id的字段类型是VARCHAR(255),而索引是B-TREE,MySQL优化器选了最烂的执行计划。

  这时候窗外天快亮了,泡面在桌上泡了半小时,汤都凉了。我盯着屏幕上的EXPLAIN结果,突然想起去年运维培训时老师说过:“VARCHAR当主键或分组字段,就是给自己挖坑。”我原以为这是吓唬新人的,结果现在真栽了。我直接把user_id改成INT,重新建索引,再跑那条GROUP BY的查询,执行时间从5秒掉到0.1秒——这时候CPU终于稳定在20%以下,告警也消停了。

文章配图,仅供参考

  第三刀是砍PHP的OPcache。我翻出那台主机的php.ini,发现opcache.enable=1,但opcache.memory_consumption还是默认的64M——这数儿是PHP5.6时代的配置,现在PHP7.4+的OPcache需要至少128M才能跑得稳。我原以为OPcache只是加速,不会影响稳定性,结果内存不够时,OPcache会频繁重启,导致每次请求都要重新编译PHP脚本,CPU直接飙高。我把memory_consumption改成256M,再设opcache.validate_timestamps=0(生产环境必须关掉,不然每次请求都检查文件修改时间,纯属浪费CPU),重启PHP-FPM后,CPU又降了5%——虽然不多,但蚊子腿也是肉。

  这时候开发老王在群里发了个截图:“我改完代码了,现在卡顿应该好了。”我问他改了啥,他说:“把那个IN列表从200个ID改成10个一组,分批查。”我差点把键盘砸了:“你早干嘛去了?我昨晚调配置、改索引、调OPcache,你今天才改代码?”他回:“我以为你们运维能搞定啊…”我回了个“滚”,然后把他拉进了一个叫“优胜劣汰”的群——里面全是之前因为代码写得烂被我们运维集体吐槽的开发。

  其实这波卡顿本来能避免。去年我们就提过要给user_id加索引、改INT类型,结果开发说“旧数据迁移麻烦”;三个月前慢查询监控就报过那条GROUP BY的SQL,开发说“测试环境没复现,先放着”;甚至昨晚我调OPcache时,发现php.ini里还有一堆PHP5.6的配置,比如magic_quotes_gpc=On——这玩意儿在PHP5.4就被废弃了,现在居然还在用!

  下一步我打算把所有PHP应用的配置模板统一管起来,用Ansible推送到所有机器,再写个脚本定期检查配置是否被手动改过——上次发现有个开发偷偷改了php.ini里的error_reporting,把E_ALL改成了E_NOTICE,导致线上报错被隐藏了半个月。至于开发那边,我已经跟老大提了:以后代码评审必须拉上运维,不然就等着被我们“优胜劣汰”吧。

(编辑:站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!