
1) 【一句话结论】实时竞价系统需以分布式架构为基础,通过请求分发、实时计算引擎、缓存+数据库分层存储、消息队列解耦,结合最终一致性策略,实现百万级QPS,核心是“快速路径”与“数据一致性折中”的平衡。
2) 【原理/概念讲解】老师口吻:实时竞价系统的核心是“快速响应”,用户请求(如广告展示请求)需在毫秒级内完成匹配、出价、返回。首先,分布式系统是基础,因为百万级QPS远超单节点承载能力,需水平扩展。流程上,请求先到请求分发层(如Nginx+Consul负载均衡),分发到多个实时计算引擎节点,计算引擎从Redis缓存快速获取广告主信息(避免数据库压力),快速匹配并计算出价,结果返回用户。存储层采用Redis(缓存实时数据)+MySQL(持久化关键数据),消息队列(如Kafka)用于异步处理日志、统计等非实时任务。关于数据一致性,由于QPS极高,采用最终一致性(缓存数据异步同步到数据库),保证数据最终一致但不实时。容错机制包括:请求分发层负载均衡(故障节点自动剔除),Redis集群高可用(主从+哨兵),消息队列持久化+消费重试(确保任务不丢失)。
3) 【对比与适用场景】
| 方案 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| Redis | 内存数据库 | 高速读写、支持数据结构、分布式 | 实时数据缓存、会话存储 | 数据持久化需额外配置,单点故障风险 |
| MySQL | 关系型数据库 | ACID事务、持久化、事务支持 | 关键业务数据持久化 | 写性能受限于磁盘,需分库分表 |
| Kafka | 分布式消息队列 | 高吞吐、持久化、分区 | 实时数据流、日志收集 | 启动延迟、消息积压风险 |
| RabbitMQ | 企业级消息队列 | 延迟低、可靠性 | 异步任务、工作流 | 单点故障影响 |
4) 【示例】
{
"request_id": "req_12345",
"user_id": "u_001",
"ad_slot": "slot_1",
"timestamp": 1672531200
}
def real_time_bid(request):
# 从Redis获取广告主信息(缓存)
advertisers = redis.get("advertisers")
if not advertisers:
advertisers = db.query("select * from advertisers")
redis.set("advertisers", advertisers, ttl=60)
# 匹配广告主并计算出价
best_bid = 0
for ad in advertisers:
bid = calculate_bid(ad, request)
if bid > best_bid:
best_bid = bid
# 返回结果
return {"request_id": request["request_id"], "winner": "ad_001", "bid": best_bid}
5) 【面试口播版答案】
面试官您好,我来回答实时竞价系统百万级QPS的设计问题。核心结论是:系统需基于分布式架构,通过请求分发、实时计算引擎、缓存+数据库分层存储、消息队列解耦,结合最终一致性策略,实现百万级QPS,核心是“快速路径”与“数据一致性折中”的平衡。首先,实时竞价流程是用户请求(如广告展示请求)快速到达分发层,通过负载均衡分发到计算节点,计算引擎从Redis缓存获取广告主信息(避免数据库压力),快速匹配并计算出价,结果返回给用户。存储层采用Redis(缓存实时数据)+MySQL(持久化关键数据),消息队列(如Kafka)用于异步处理日志、统计等非实时任务。数据一致性方面,由于QPS极高,采用最终一致性:缓存数据异步同步到数据库,保证数据最终一致但不实时。容错机制包括:请求分发层负载均衡(如Nginx+Consul),计算节点故障时自动切换;Redis集群高可用(主从+哨兵);消息队列持久化+消费重试,确保任务不丢失。这样系统既能支撑百万级QPS,又能保证高可用和容错。
6) 【追问清单】
7) 【常见坑/雷区】