1) 【一句话结论】采用微服务+分布式架构,通过负载均衡分发请求、Redis缓存热点数据、消息队列异步处理核心任务,结合数据库分库分表与限流熔断机制,实现高并发、数据一致性与系统可扩展性。
2) 【原理/概念讲解】老师口吻,解释关键技术:
- 负载均衡:像交通枢纽,将请求分发到多台服务器,避免单点过载(类比:城市主干道分叉,分散车流)。
- 缓存(Redis):像超市货架,存储热点数据(如课程信息、用户信息),减少数据库压力(读多写少场景适用)。
- 消息队列(如Kafka):像快递中转站,异步处理扣减库存、发送通知等任务,解耦主流程与异步任务(类比:下单后快递员不立即派送,先入中转站,避免阻塞下单)。
- 分库分表:像把大仓库分成小仓库,按课程ID/用户ID分表,提高数据库读写性能(解决单库瓶颈)。
- 限流:像交通限速,控制请求速率(如令牌桶算法),防止系统崩溃(类比:高速公路限速,避免拥堵)。
- 数据一致性:选课时,采用最终一致性(异步扣减库存,通过消息确认),保证用户选课成功后库存最终扣减成功。
3) 【对比与适用场景】
| 对比项 | 缓存(Redis) | 数据库(MySQL) | 消息队列(Kafka) |
|---|
| 定义 | 内存存储,速度快 | 磁盘存储,持久化 | 异步消息传递系统 |
| 特性 | 读写快,适合热点数据 | 事务支持,数据一致性强 | 异步、解耦、高吞吐 |
| 使用场景 | 读多写少的热点数据(课程列表、用户信息) | 写操作多、需要事务的选课记录、库存表 | 处理高并发异步任务(扣减库存、发送通知) |
| 注意点 | 需设置过期时间,避免数据过时;高并发下可能缓存击穿/雪崩 | 执行复杂查询慢,需分库分表 | 需消息确认机制,避免消息丢失;延迟处理影响体验 |
4) 【示例】选课流程伪代码:
用户发起选课请求:
- 负载均衡分发请求到应用服务器。
- 应用服务器检查限流(令牌桶算法)。
- 查询Redis(课程ID为key):
- 存在 → 返回课程信息。
- 不存在 → 查询MySQL(分库分表,按课程ID分表),将数据存入Redis(过期1小时)。
- 验证用户是否已选该课程(Redis/数据库查询)。
- 未选 → 发送消息到Kafka(内容:课程ID、用户ID、扣减数量)。
- 返回选课成功响应。
5) 【面试口播版答案】
面试官您好,针对高并发选课系统,我设计的架构核心是微服务+分布式技术,通过负载均衡分发请求、Redis缓存热点数据、消息队列异步处理库存扣减等任务,结合数据库分库分表与限流熔断机制。具体来说:
- 负载均衡将请求分发到多台应用服务器,避免单点过载;
- Redis缓存课程信息、用户信息等热点数据,减少数据库压力;
- 消息队列(如Kafka)异步处理扣减库存、发送通知等任务,避免阻塞主流程;
- 数据库通过分库分表(按课程ID/用户ID分表),提高读写性能;
- 限流机制(令牌桶)控制请求速率,防止系统崩溃。
这样既能保证高并发处理能力,又能保证数据一致性和系统可扩展性。
6) 【追问清单】
- 问:如何保证选课过程中数据一致性?
答:采用最终一致性,选课成功后通过消息队列异步扣减库存,库存扣减成功后发送确认消息,失败则重试,确保最终数据一致。
- 问:如何处理缓存雪崩?
答:设置缓存过期时间(如1小时),采用随机过期时间;查询失败时直接查询数据库并回写缓存,避免雪崩。
- 问:系统如何水平扩展?
答:应用服务器通过负载均衡扩展,数据库分库分表扩展,缓存Redis集群扩展,消息队列Kafka集群扩展。
- 问:如何处理选课超时或失败?
答:设置请求超时(3秒),超时重试;库存扣减失败重试或回滚,通知用户。
- 问:是否考虑容灾?
答:数据库主从复制,Redis哨兵模式,消息队列多副本,确保高可用。
7) 【常见坑/雷区】
- 直接用数据库处理高并发读写,忽略缓存,导致数据库压力过大。
- 消息队列选择不当(如RabbitMQ同步模式),阻塞主流程。
- 分库分表导致事务跨库,无法保证数据一致性。
- 限流策略不合理(固定速率),部分用户无法访问。
- 缓存未设置过期时间,导致数据过时或雪崩。