1) 【一句话结论】
在高并发场景下,通过监控定位到数据库慢查询导致接口超时,优化SQL(减少JOIN表数、添加索引)并配置读写分离后故障解决,系统性能恢复,响应时间从2000ms降至100ms以内,错误率回到1%以下。
2) 【原理/概念讲解】
老师会解释高并发下数据库瓶颈的核心原因:
- 锁竞争:行级锁或表锁导致多请求争抢资源,类似“餐厅点餐时多人抢同一个厨师(锁),导致排队时间长”;
- 慢查询:复杂SQL(如多表JOIN、无索引)导致I/O高、CPU占用高,类似“厨师做复杂菜(SQL)耗时久,影响整体出餐速度”;
- 资源争抢:高并发下CPU、内存等资源被过度占用,类似“餐厅同时有1000人点餐,厨师(CPU)忙不过来,导致出餐延迟”。
排查需遵循“分阶排查”逻辑:先应用层(日志、熔断),再网络层,最后数据库层(慢查询日志、锁监控)。
3) 【对比与适用场景】
- 应用层排查:
- 定义:检查应用代码、网络、缓存等上层问题;
- 特性:快速定位,关注请求路径、错误码;
- 使用场景:接口超时、错误率飙升;
- 注意点:需日志+监控覆盖,优先排查。
- 数据库排查:
- 定义:检查SQL执行、锁、资源等底层问题;
- 特性:深入底层,关注执行计划、锁等待;
- 使用场景:响应时间慢、资源占用高;
- 注意点:需慢查询日志+锁监控工具(如Prometheus+PGStats)。
4) 【示例】
假设系统是Tencent的某API服务,高并发(QPS从1000突增到5000)时,监控显示响应时间从100ms飙升至2000ms,错误率从1%升至30%。
- 初步分析:应用层日志无异常,网络正常,怀疑数据库问题;
- 排查:通过慢查询日志(工具:Prometheus+PGStats)发现一个复杂关联查询(JOIN 5张表,无索引)的执行时间从10ms变为500ms,且锁等待时间从0ms增至200ms;
- 解决方案:优化SQL(减少JOIN表数至3张表,添加索引),配置读写分离(读请求分流到从库)。优化后,查询时间从500ms降至10ms,锁等待消失,响应时间恢复到100ms以内,错误率回到1%以下。
5) 【面试口播版答案】
面试官好,我来分享一个处理过的系统高并发故障案例。当时我们服务的API在高并发(QPS从1000突增到5000)时,监控显示响应时间从100ms飙升至2000ms,错误率从1%升至30%。初步分析:应用层日志无异常,网络正常,怀疑是数据库问题。排查时,通过慢查询日志发现一个复杂关联查询(JOIN 5张表)的执行时间从10ms变为500ms,导致锁竞争。解决方案是优化SQL(减少JOIN表数,添加索引)并配置读写分离,故障解决后响应时间恢复到100ms以内,错误率回到1%以下。
6) 【追问清单】
- 为什么选择优化SQL而不是直接分库分表?→ 因为该表数据量不大(百万级),优化SQL成本更低,且分库分表会引入复杂性。
- 故障恢复时间是多少?→ 约15分钟,包括分析、优化SQL和部署。
- 是否影响业务?→ 影响较小,故障发生在凌晨3点,不影响核心业务,恢复后性能稳定。
- 后续是否有预防措施?→ 建立慢查询阈值告警(如执行时间>100ms触发),定期优化SQL,监控锁等待情况。
- 如果是分布式系统,如何排查?→ 需结合分布式追踪(如SkyWalking)定位到具体节点,再分析该节点的数据库查询。
7) 【常见坑/雷区】
- 只描述现象,没分析过程:比如只说“接口慢了”,没讲如何定位到数据库;
- 解决方案不具体:比如只说“优化了”,没说明优化了什么(如减少JOIN);
- 忽略监控的重要性:没提到通过监控发现异常;
- 假设的故障原因不成立:比如假设是缓存问题,但实际是数据库慢查询;
- 忽略后续验证:没说明故障解决后是否验证性能恢复。