ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

后端性能优化实战:从慢查询到QPS翻十倍

后端性能优化实战:从慢查询到QPS翻十倍 第一刀揪出慢查询别靠猜我打开MySQL的慢查询日志把long_query_time设成0.1秒跑了一天。结果触目惊心一个订单列表接口循环里查了二十次用户表。N1查询是后端性能的头号杀手它不报错只拖死你。改成一次JOIN查完这个接口的数据库耗时从430毫秒掉到12毫秒。工具用pt-query-digest别手工翻日志效率差十倍。第二刀索引不是万能的没索引是万万不能的那条三百万行的全表扫描问题出在WHERE status1 AND created_at2023-01-01上。status区分度太低建了也没用。我改成联合索引(created_at, status)让时间范围先过滤再筛状态。索引设计的核心是区分度和顺序把最能缩小范围的条件放最左边。但索引不是越多越好每个索引都拖慢写入。我顺手删了三个冗余索引写入性能涨了15%。第三刀缓存不是加一层就完事数据库优化完QPS上到2500就上不去了。我加Redis缓存热点数据但立刻遇到缓存穿透——大量请求查不存在的ID全部打到数据库。解决方案是布隆过滤器加空值缓存。缓存用对了是性能倍增器用错了是数据一致性地雷。我设置了随机过期时间防止雪崩热点key永不过期但异步更新。这一层加上QPS直接跳到5000。第四刀连接池和线程池配错了全是坑之前连接池最大连接数设了200数据库最大连接也是200一压测就互相等。连接池不是越大越好数据库扛不住反而更慢。我把应用侧连接池降到50数据库最大连接提到500配合连接复用等待时间几乎消失。线程池同理IO密集型任务设成CPU核数的2到4倍队列用有界队列加拒绝策略防止内存被任务对象撑爆。第五刀异步化把能拆的全拆了订单创建后要发短信、写日志、更新统计这些同步做拖慢主流程。我用MQ把非核心链路全部异步化主流程只写订单和扣库存。同步是性能的敌人异步是解药但异步必须解决幂等和最终一致性。消息消费端做了去重表保证重复消费不出错。这一步让核心接口响应时间从300毫秒降到80毫秒。第六刀压测验证数据说话每改一处我都用JMeter压一遍。记录QPS、RT、错误率、CPU和内存。没有压测的优化是盲人摸象你永远不知道下一刀该砍哪里。最终一轮压测QPS稳定在8000P99响应时间110毫秒数据库CPU从90%降到35%。老板在群里发了个红包我睡了十个小时。回头复盘这六刀没有一刀是黑科技全是基本功。慢查询、索引、缓存、连接池、异步、压测——性能优化不是玄学是把每个环节的账算清楚把每个瓶颈的根挖出来。很多人一上来就想着换架构、上分库分表其实80%的性能问题在SQL和缓存层就能解决。先别急着造火箭把螺丝拧紧QPS翻十倍没你想的那么难。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进