从 8s 白屏到首屏秒开:我靠三张小抄治好了站点的"查询癌、缓存瘫、资源胖"

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

上周有个老站迁移到新机器,配置翻倍,速度反而更慢了。我盯着 Chrome 的瀑布流看了十分钟,CPU 没炸、带宽没满,就是各种资源排队等得花儿都谢了。最后发现不是机器问题,是我之前"能跑就行"埋的雷集体炸了。整理了三张现在贴显示器边上的备忘,都是血换来的。

第一张:查询小抄——"少查一次"比"查快一点"值钱十倍

以前我迷信 EXPLAIN 调索引,后来悟了:业务层少发一条 SQL,收益比索引优化高得多。现在改需求先过这三关:

1. 列表页计数别 SELECT COUNT(*):十万级数据就开始肉疼。我现在用 Redis 做个异步计数器,或者干脆用 SHOW TABLE STATUS 估个数,误差 5% 用户根本无感。真要精确,单独搞个计数表用触发器维护,别每次翻页都全表扫。

2. 关联查询先问能不能拆:用户详情页以前 with 了七八个关联,现在改成主查询只拿核心字段,侧边栏用 AJAX 懒加载。首屏 SQL 从 11 条压到 2 条,感知速度反而更快——用户先看到头像昵称,其他模块转圈圈等着,体验比白屏 3 秒强。

3. 埋个慢查询"闹钟":MySQL 的 long_query_time 我设 0.5 秒,但生产环境不敢随便开日志。折中办法是程序层包个 DB 监听,单次查询超 200ms 就往钉钉丢一条。上周抓到个后台统计报表,WHERE 里用了 DATE(created_at),函数套字段索引直接失效,改成范围查询从 4 秒掉到 40ms。

第二张:缓存小抄——"过期策略"比"命中率"更要命

我缓存踩过最蠢的坑:命中率 98%,但毛用没有。因为热点数据全挤在一个 key,并发一高 Redis 单节点 CPU 被打满。现在我的缓存分三层:

1. 本地缓存抗突发:ThinkPHP 的 think-cache 我配了个 APCu 做 L1,TTL 设 30 秒。同样的 key 本地命中就不走 Redis,突发流量先被这层吃掉。注意内存别超,我设了 64MB 上限,LRU 淘汰,爆了就回退。

2. Redis key 带"版本号":以前改数据结构,缓存里还是老格式,反序列化报错报得怀疑人生。现在 key 命名带 v1/v2,升级时直接换前缀,老数据自然过期。清理脚本?不存在的,让它自生自灭。

3. 缓存穿透用"空值占位":用户搜不存在的词,以前每次透到数据库。现在查不到也写个空字符串进 Redis,TTL 设 60 秒。恶意扫描?让他扫,Redis 扛得住。但注意空值别和正常数据混,我单独加个 __empty__ 后缀区分。

4. 最狠的一招:缓存和 DB 的"时间差":大促时库存缓存,我故意让 Redis 比 MySQL 慢 3 秒同步。用户下单先扣缓存,异步队列去落库。这 3 秒窗口超卖?概率有,但业务上接受,总比数据库锁表全站 503 强。当然得配个兜底对账,晚上跑脚本平账。

第三张:静态资源小抄——"加载顺序"比"文件大小"更能救命

CDN 开了、图片压缩了、Gzip 启了,Lighthouse 还是黄?我后来发现是加载顺序在搞鬼:

1. CSS 别用 @import:以前图省事,主 CSS 里 @import 了三个字体文件。结果渲染被阻塞,白屏多等 600ms。现在全改成 link 标签,放头部并行加载。字体文件?用 font-display: swap,先出系统字体顶着,加载完再换,用户感知不到闪烁。

2. JS 分"骨架"和"血肉":Vue 项目我把路由拆懒加载了,但入口文件还有 800KB。后来把 Vue 运行时、路由、状态管理这些"骨架"单独打包 vendors,CDN 引;业务代码按路由拆,首页只加载 120KB。关键:骨架加 defer,业务 JS 放底部,DOM 先渲染,JS 慢慢补交互。

3. 图片"说谎"技巧:首屏大图我用了个骚操作——先加载 1% 质量的模糊占位图(2KB),同时 img 标签挂 data-src 存原图地址。IntersectionObserver 检测到进视口再换真图。用户看到的是"从模糊变清晰",比空白等加载舒服得多。WebP?当然上了,但配个 onerror 回退 PNG,兼容老浏览器。

4. HTTP/2 的坑:以为开了 HTTP/2 就可以随便拆包?我试过把 JS 拆成 50 个小模块,结果队头阻塞没了,但请求开销暴涨,总时间反而更差。现在控制在 6-8 个关键包,其余懒加载。工具用 webpack-bundle-analyzer,每次打包看一眼,哪个包胖了立刻揪出来。

最后说个反直觉的

有天我把全站缓存时间从 1 小时调到 5 分钟,CPU 涨了 8%,但转化率涨了 12%。因为价格信息准了,用户下单犹豫少了。性能优化别只盯着技术指标,最终看的是业务指标。现在我的监控面板并排摆着:TTFB、FCP、转化率、客诉率,四个数一起看,单看一个容易魔怔。

这三张小抄我打印塑封了,改需求、review 代码、上线前 check 都过一遍。不是啥高深架构,就是提醒自己:慢,往往不是因为某个地方慢,是因为每个地方都"差不多",加起来就崩了。

评论9
回复 · 9
知夏45
知夏45 新手 · #9 ·
感谢分享!
MayaPark
MayaPark 新手 · #8 ·
同求,期待更新
MellowBee
MellowBee 新手 · #7 ·
写得很清楚,收藏了
Alex
Alex 新手 · #6 ·
写得很清楚,收藏了
Ivy
Ivy 新手 · #5 ·
写得很清楚,收藏了
Xena
Xena 新手 · #4 ·
学到了,顶一下
GraceWei
GraceWei 新手 · #3 ·
写得很清楚,收藏了
Drew
Drew 新手 · #2 ·
学到了,顶一下
CoolKid🌸
CoolKid🌸 新手 · #1 ·
写得很清楚,收藏了
微信客服 微信客服