
1) 【一句话结论】铁路客票系统在高峰期高并发下,需通过“缓存(Redis)+读写分离+分库分表(结合全局ID与缓存聚合)+索引优化(高频查询字段索引,权衡写性能)”的组合策略,分层缓解数据库压力,核心是减少数据库访问并分散压力,同时解决跨库关联、缓存失效等复杂问题。
2) 【原理/概念讲解】老师口吻解释关键技术:
3) 【对比与适用场景】
| 技术方案 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| 缓存策略 | 使用Redis等缓存存储热点数据 | 减少数据库访问,提升响应速度 | 高频查询、热点数据(如热门车次、票价) | 需解决雪崩(随机过期)、击穿(互斥锁/预加载),避免缓存穿透 |
| 读写分离 | 主库写,从库读,通过binlog同步 | 分散读压力,提升读性能 | 读多写少场景(如12306查询多,购票少) | 需保证从库数据一致性,避免脏读 |
| 分库分表 | 水平拆分(按业务/区域)或垂直拆分(按字段) | 扩展数据库容量,提升并发 | 数据量巨大,单库无法承载 | 需全局ID(如Snowflake),跨表关联复杂,需缓存聚合减少跨库 |
| 索引优化 | 为表字段创建索引,加速查询 | 提升查询效率,但增加写成本 | 高频查询字段(如车次号、日期、用户ID) | 避免过度索引,定期用EXPLAIN评估,删除冗余索引 |
4) 【示例】(分库分表后跨表查询,订单表与车次表分库,用全局ID关联):
# 跨库查询订单与车次信息(订单表在order_db,车次表在train_db)
def get_order_with_train(order_id):
cache_key = f"order_{order_id}_train"
train_info = redis.get(cache_key)
if train_info:
return json.loads(train_info)
# 从订单表查订单ID,再查车次表(跨库)
sql_order = "SELECT * FROM order_db.order WHERE id = %s"
order = db_order.query(sql_order, (order_id,))
if not order:
return None
train_id = order['train_id'] # 订单关联车次ID
sql_train = "SELECT * FROM train_db.train WHERE id = %s"
train = db_train.query(sql_train, (train_id,))
if train:
order['train'] = train
redis.setex(cache_key, 3600, json.dumps(order))
return order
5) 【面试口播版答案】(约90秒):
“面试官您好,铁路客票系统在春运等高峰期面临高并发请求,数据库优化需综合多种策略。首先,缓存策略:用Redis存储热门车次、票价等热点数据,查询车次信息时先从缓存获取,若缓存无则查询数据库并更新缓存,减少数据库压力。其次,读写分离:主库负责写操作(如购票、订单插入),从库负责读操作(如查询车次、订单状态),分散读压力,提升读性能。然后,分库分表:按地区(如北京、上海)分库,或按业务模块(票务、用户)分表,避免单库数据量过大,比如北京车次数据存入db_beijing。全局ID(如雪花算法生成的订单ID)解决跨表关联,订单表通过订单ID关联车次表。跨库查询时,通过缓存聚合(预加载热门车次与订单关联数据)减少跨库操作。最后,索引优化:为高频查询字段(如车次号、日期、用户ID)创建复合索引,比如查询“北京到上海2024-01-01的车次”时,创建(出发地,目的地,日期)的复合索引,提升多条件查询效率。这些措施组合起来,能有效支撑高并发读写,缓解数据库压力。”
6) 【追问清单】及回答要点:
7) 【常见坑/雷区】