1. 高并发面试题解析:从原理到实战
高并发系统设计是互联网大厂面试的必考题目,也是实际业务中最具挑战性的技术场景之一。最近帮团队面试了几位候选人,发现很多开发者对高并发的理解还停留在"加机器"的层面。今天我就结合12306抢票、秒杀系统等经典场景,拆解高并发的核心考点和解决方案。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 高并发系统核心指标
2.1 QPS与TPS的本质区别
QPS(Queries Per Second)和TPS(Transactions Per Second)经常被混为一谈,但在面试中必须明确区分:
- QPS是服务端每秒能处理的请求数
- TPS是业务层面每秒完成的事务数(如创建订单)
注意:一个下单事务可能包含10+个QPS(查库存、扣减、创建订单等)
2.2 响应时间百分位值
平均响应时间会掩盖问题,我们更关注:
- P99(99%请求的响应时间)
- P999(99.9%请求的响应时间)
在百万QPS系统中,即使0.1%的慢请求也会导致每秒1000个请求堆积。
3. 高并发三板斧
3.1 缓存架构设计
Redis不是银弹,缓存设计要考虑:
- 多级缓存:本地缓存 + 分布式缓存
- 缓存击穿解决方案:
- 互斥锁(Redis SETNX)
- 逻辑过期时间
- 热点Key探测与隔离
java复制// 典型双重检查锁实现
public Object getData(String key) {
Object value = redis.get(key);
if (value == null) {
if (redis.setnx(key_mutex, 1)) {
value = db.get(key);
redis.set(key, value);
redis.del(key_mutex);
} else {
Thread.sleep(50);
return getData(key);
}
}
return value;
}
3.2 消息队列削峰
对比主流消息队列选型:
| 特性 | Kafka | RocketMQ | RabbitMQ |
|---|---|---|---|
| 吞吐量 | 最高 | 高 | 中 |
| 延迟 | 毫秒级 | 毫秒级 | 微秒级 |
| 事务消息 | 支持 | 支持 | 不支持 |
| 适用场景 | 日志处理 | 订单业务 | 实时通知 |
3.3 数据库扩展方案
3.3.1 读写分离陷阱
很多候选人会脱口而出"读写分离",但要警惕:
- 主从延迟导致脏读
- 从库越多同步压力越大
- 需要配合业务做妥协(如某些查询强制走主库)
3.3.2 分库分表实践
我们采用ShardingSphere实现的分库分表策略:
- 用户维度分库(16个库)
- 订单表按月分表(每月一张表)
- 使用基因法避免跨库JOIN
4. 前沿技术方案
4.1 虚拟线程实战
Java19的虚拟线程确实能大幅提升并发能力:
java复制try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
IntStream.range(0, 10_000).forEach(i -> {
executor.submit(() -> {
Thread.sleep(Duration.ofSeconds(1));
return i;
});
});
}
但要注意:
- 仍受限于后端服务吞吐量
- I/O密集型场景效果最佳
- 需要配合异步编程模型
4.2 分布式限流算法
对比三种限流实现:
- 令牌桶(Guava RateLimiter)
- 漏桶算法
- 滑动窗口(Redis + Lua)
推荐Redission的RRateLimiter:
java复制RRateLimiter limiter = redisson.getRateLimiter("myLimiter");
limiter.trySetRate(RateType.OVERALL, 100, 1, RateIntervalUnit.SECONDS);
if (limiter.tryAcquire()) {
// 处理请求
}
5. 经典场景剖析
5.1 12306余票查询优化
关键技术点:
- 预计算余票(出发前2小时刷新)
- 读写分离+缓存(余票信息缓存在Redis)
- 分段提交(先占座后支付)
5.2 秒杀系统设计
我们的实战架构:
- 前端:
- 静态化页面
- 按钮灰度+倒计时校正
- 网关层:
- 恶意请求拦截
- 流量削峰
- 服务层:
- 内存标记+Redis原子扣减
- 消息队列异步下单
- 数据层:
- 库存字段单独拆表
- 乐观锁更新
6. 面试避坑指南
最近三个月面试中常见的错误答案:
- "用Redis就能解决高并发"(不考虑持久化、一致性)
- "加服务器就能扩容"(忽视无状态改造)
- "所有查询都走缓存"(不处理缓存穿透)
- "分库分表能解决所有性能问题"(不分场景滥用)
建议候选人准备:
- 至少深入一个中间件(Redis/Kafka)
- 能说清楚CAP取舍
- 有实际调优经验(不只是理论)
- 了解云原生方案(K8s自动扩缩容)
