
1) 【一句话结论】
采用“CDN+负载均衡+分布式缓存+异步消息队列+分库分表数据库”的分层架构,通过缓存预热、异步解耦、分库分表扩容、重试与死信队列保障,确保百万级并发下的低延迟、高可用及数据一致性。
2) 【原理/概念讲解】
老师口吻解释关键概念:
3) 【对比与适用场景】
| 策略 | 分库方式 | 分表方式 | 适用场景 | 注意点 |
|---|---|---|---|---|
| 按广告ID范围分库 | 每库存储固定范围广告ID(如库1存ad_1-ad_10000,库2存ad_10001-ad_20000) | 按时间分表(如表名ad_20240501, ad_20240502) | 广告ID规模大,需水平扩展 | 需维护分片路由表,扩容时需迁移数据 |
| 按广告类型分库 | 每库存储特定类型广告(如游戏内广告、游戏外广告) | 按时间分表 | 广告类型多,需按类型隔离 | 类型变化时需调整分库 |
| 触发方式 | 实现方式 | 数据量 | 适用场景 |
|---|---|---|---|
| 定时任务 | 每日凌晨0点启动,拉取当日热门广告数据(如过去7天点击量TOP10广告) | 1000条左右 | 热门广告需提前加载 |
| 用户行为触发 | 用户登录时,拉取其历史点击广告(如过去30天点击过的广告) | 50条左右 | 个性化广告预热 |
| 机制 | 实现方式 | 处理逻辑 |
|---|---|---|
| 重试机制 | 消息消费失败后,重试3次(间隔1秒、5秒、10秒) | 避免瞬时故障导致数据丢失 |
| 死信队列 | 重试失败后,消息进入死信队列(DLQ) | 人工处理或批量清理 |
4) 【示例】
伪代码展示典型请求流程:
用户打开游戏 → 客户端发送开屏广告请求 → Nginx负载均衡分发到服务实例A
服务A检查Redis(key=用户ID+广告类型,如"u1234-ad1")→ 若存在 → 直接返回缓存数据(广告图片/信息)
若不存在 → 向Kafka发送“拉取广告”任务(包含用户ID、广告类型、请求时间戳)
后台服务B(广告数据拉取服务)消费Kafka消息 → 从分布式MySQL(分库分表)拉取广告数据(如广告ID、图片URL、描述) → 存入Redis(key=用户ID+广告类型,value=广告数据) → 返回给服务A
服务A将广告数据返回Nginx → Nginx返回给客户端(用户设备)
(注:分库分表时,服务B根据广告ID范围选择对应库,按时间分表选择对应表;缓存预热任务每日凌晨0点启动,拉取当日热门广告存入Redis;异步任务失败后重试3次,失败后进入死信队列)
5) 【面试口播版答案】
“各位面试官好,针对百万级用户同时请求的开屏广告系统设计,我的核心思路是构建‘分层解耦、缓存优先、异步处理、分库分表扩容’的架构,确保高并发下的低延迟与高可用。首先,前端通过CDN分发请求,减少网络延迟;中间层用Nginx负载均衡分发到多个广告服务实例,避免单点故障;核心是缓存策略,优先从Redis获取广告数据,减少数据库压力;对于非缓存数据,通过Kafka异步拉取广告,避免阻塞主流程。技术选型上,负载均衡选Nginx(高性能轮询算法,适合静态资源),缓存选Redis(内存+持久化,支持热点数据),消息队列选Kafka(高吞吐、持久化),数据库用分布式MySQL(按广告ID范围分库,按时间分表,扩展容量)。高并发处理方面,通过缓存减少数据库访问,异步任务解耦请求和广告拉取,负载均衡保证请求分发均匀,CDN就近分发提升响应速度。同时,考虑缓存预热(每日凌晨拉取热门广告存入Redis),异步任务重试与死信队列保障数据可靠性,分库分表支持百万级广告数据存储。整体来看,这个方案能支撑百万级并发,同时保证广告加载的实时性和稳定性。”
6) 【追问清单】
7) 【常见坑/雷区】