从 4.2s 到 380ms:我把一个"能跑就行"的老站扒了三层皮,发现性能瓶颈全藏在我懒得改的习惯里

小助手
小助手 版主圣羽星庭 勋望元宿志愿先锋
社区管理
站长杂谈 53 浏览 3 回复

上周帮朋友收拾一个跑了五年的资讯站,后台卡、前台慢,用户骂,广告商催。我一开始以为是服务器不行,结果换完 8 核 16G 还是卡。最后发现性能杀手全是我(和前任开发者)随手写的"能跑就行"的代码。整理几条最痛的,给老站改造提个醒。

一、查询:别信 ORM 的"智能",它只会智能地坑你

打开慢查询日志,排名第一的是条 2.1s 的"最新文章":

```
Article::with(['category', 'tags', 'author', 'comments'])
->orderBy('id', 'desc')
->limit(10)
->select();
```

看着人畜无害,实际 `comments` 是文章-评论一对多,`with` 预加载直接拖了 8000 条评论出来。更坑的是 `tags` 多对多,中间表没索引,全表扫描。

我的改法:拆。首页只查文章基础字段,标签和评论数走单独统计查询,作者信息扔 Redis。`with` 不是不能用,得看场景,首页这种高频接口,宁可多查两次小的,别一次查个大的。

还有个隐藏雷:`whereMonth('created_at', 6)` 这种时间函数查询,MySQL 没法用索引。五年数据量一上来,全表扫描跑不掉。改成范围查询 `whereBetween`,同样的逻辑,从 1.8s 降到 12ms。

二、缓存:我之前的"缓存"其实是给自己埋的延迟雷

老代码里有段经典写法:

```
$articles = Cache::get('home_articles');
if (!$articles) {
$articles = Article::... // 巨慢查询
Cache::set('home_articles', $articles, 3600);
}
```

缓存失效那一刻,N 个并发请求同时穿透到数据库,直接打爆。之前流量小没感觉,上周被爬虫一撞,MySQL CPU 飙到 100%。

改成互斥锁 + 异步回源:缓存过期后第一个请求拿锁去查库,其他请求返回旧数据(允许短暂脏读)。ThinkPHP 用 `cache->remember` 配合 `lock` 或者上分布式锁,实在懒得折腾,至少加个随机过期时间,别让所有 key 同时死。

另外提醒:别缓存整条 HTML 又忘了清。我改了篇文章标题,前台还是旧的,排查半小时发现是页面缓存,后台更新文章没触发清理。现在我的规矩是——凡是缓存,必须配对应的失效事件,哪怕多写十行代码。

三、静态资源:CDN 不是万能药,源站配置烂照样白搭

这站图片用了 OSS+CDN,但首页速度还是拉胯。Chrome DevTools 一看,首屏 47 个请求,其中 23 个是各种尺寸的缩略图,最大的 2.3MB,没 WebP,没懒加载。

我的处理清单:

1. 图片统一走 OSS 图片处理参数,`?x-oss-process=image/resize,w_400/format,webp`,URL 里直接带规则,不用后端生成多份
2. 非首屏图片加 `loading="lazy"`,瀑布流用 Intersection Observer 手动控制
3. CSS/JS 上 CDN 时,检查 gzip 和 brotli 有没有开。这站之前只开了 gzip,brotli 没配,体积差 20%
4. 字体文件原来用了 4 个完整中文字体,2.1MB。砍到只用系统字体栈,`font-family: -apple-system, "PingFang SC", sans-serif`,特殊标题用子集化后的 woff2,剩 18KB

最隐蔽的一个:CDN 回源走了 HTTPS,但源站证书链不全,部分运营商节点握手失败,默默回退到 HTTP,然后被浏览器 mixed content 拦截。用户看到的是图片裂了,我查了一晚上日志才定位。

四、一个反直觉的结论

改完这三层,首页 TTFB 从 4.2s 降到 380ms,不是因为我加了什么黑科技,是删掉了过度设计。之前为了"优雅"搞了太多抽象层:模型事件里套服务,服务里调仓库,仓库里再触发事件,一个请求串了 17 个类。现在首页接口直接写查询,缓存用文件+Redis 两级,复杂业务才上事件。

性能优化有时候不是做加法,是承认自己的代码没那么多需要"预留扩展性"的地方。先跑起来,再谈优雅。

你们老站改造踩过哪些"看起来没问题"的坑?

评论3
回复 · 3
Knox
Knox 新手 · #3 ·
感谢分享!
郭英怡
郭英怡 新手 · #2 ·
已解决,谢谢楼主
🐱汽水🎐
🐱汽水🎐 新手 · #1 ·
写得很清楚,收藏了
微信客服 微信客服