1) 【一句话结论】
618高并发下系统响应延迟的核心原因是数据库连接池资源耗尽导致查询超时(占延迟主要部分),其次是Redis缓存失效和消息队列积压,需按优先级优化:优先解决连接池问题,再优化缓存,最后处理队列积压。
2) 【原理/概念讲解】
老师口吻解释关键问题:
- 数据库连接池瓶颈:高并发时,数据库连接池的线程/连接资源被大量请求占用,查询操作(如库存查询、用户信息获取)因等待连接而超时,导致响应延迟。排查方法:检查数据库慢查询日志中I/O时间占比高的SQL(如
SELECT stock FROM product WHERE product_id=?因缺少索引,I/O时间从1ms飙升至1000ms),或监控数据库CPU、磁盘I/O指标。类比:餐厅高峰期,服务员(数据库线程)忙不过来,顾客(请求)等待时间长。
- Redis缓存失效:Redis缓存未命中,请求直接访问数据库,导致数据库压力骤增。例如订单详情页,缓存未更新,每次请求都查数据库。
- 消息队列积压:下单后消息写入队列,消费者处理速度跟不上,队列中消息积压,后续下单请求被阻塞或超时。类比:餐厅厨房(消费者)出餐慢,导致顾客排队(队列积压)。
3) 【对比与适用场景】
| 方案 | 定义 | 特性 | 使用场景 | 注意点 |
|---|
| 分库分表 | 将数据库按业务或数据量拆分到多个数据库实例或表 | 跨库查询复杂,需分布式事务支持 | 数据量巨大(如订单表10亿条),单库无法承载 | 需解决数据倾斜(如按时间+哈希分片),分布式事务复杂 |
| Redis缓存 | 基于内存的键值存储,用于数据快速访问 | 读写快,支持数据过期 | 频繁读操作,数据变化不频繁(如商品信息、用户信息) | 需防缓存雪崩/穿透,需预热热点数据 |
| 消息队列 | 解耦系统,异步处理业务 | 削峰填谷,保证系统稳定性 | 业务流程中步骤间依赖(如下单后通知库存、支付) | 队列积压、消息丢失,需动态扩容消费者 |
4) 【示例】
- 分库分表:订单表按下单时间按月分库,如
order_2024_06存储2024年6月订单,查询时根据时间范围选择对应库(避免全表扫描)。伪代码:SELECT * FROM order_2024_06 WHERE order_id > ?。
- Redis缓存预热:启动时加载热门商品数据到Redis,key为
product:hot:id,value为商品信息,过期时间30分钟。请求时先查缓存,未命中再查数据库。
- 消息队列:下单后,将订单信息发送到Kafka主题“order-create”,消费者处理库存扣减。当队列长度超过1000时,动态增加消费者实例(如从2个扩容到5个),提高处理速度。
5) 【面试口播版答案】
“618订单量10万+/小时,系统响应延迟,核心问题是数据库连接池耗尽,导致查询库存、用户信息等操作超时。同时,Redis缓存未命中,每次请求都查数据库,加剧压力;消息队列消费者处理慢,消息积压。优化:分库分表按月拆分订单表,减少单库压力;Redis启动时预热热门商品数据,减少数据库压力;消息队列根据队列长度动态扩容消费者,实现削峰填谷。比如分库分表后,查询6月订单只访问对应库,缓存预热加载热门商品,队列积压时扩容消费者。”
6) 【追问清单】
- 问题1:如何排查数据库具体瓶颈?
回答要点:检查慢查询日志中I/O时间占比高的SQL,优化索引或分库分表。
- 问题2:缓存策略如何设计?
回答要点:设置合理过期时间(如5分钟),用布隆过滤器防缓存穿透,随机过期防雪崩。
- 问题3:消息队列如何监控?
回答要点:监控队列长度、延迟,队列>1000时告警并动态扩容消费者。
- 问题4:分库分表如何解决数据倾斜?
回答要点:按时间+哈希分片(如订单表按下单时间哈希分库),避免某库压力过大。
- 问题5:消息队列积压时如何处理?
回答要点:增加消费者实例或优化处理逻辑(如消息分片处理)。
7) 【常见坑/雷区】
- 坑1:分库分表引入跨库查询复杂,需分布式事务,可能影响事务一致性。
- 坑2:Redis缓存雪崩导致大量请求击穿数据库,需随机过期或热备缓存。
- 坑3:消息队列积压时消费者处理慢,可能导致业务超时,需动态扩容。
- 坑4:数据库索引缺失导致查询效率低,需检查慢查询日志优化。
- 坑5:Redis缓存过期时间设置不当,导致数据过时或击穿(热点数据同时失效)。