51mee - AI智能招聘平台Logo
模拟面试题目大全招聘中心会员专区

铁路客票系统(如12306)在高峰期(如春运)面临高并发请求,数据库如何优化以支撑高并发读写?请说明具体优化措施(索引、分库分表、读写分离、缓存策略等)。

中国铁路信息科技集团有限公司运维技术研究难度:中等

答案

1) 【一句话结论】铁路客票系统在高峰期高并发下,需通过“缓存(Redis)+读写分离+分库分表(结合全局ID与缓存聚合)+索引优化(高频查询字段索引,权衡写性能)”的组合策略,分层缓解数据库压力,核心是减少数据库访问并分散压力,同时解决跨库关联、缓存失效等复杂问题。

2) 【原理/概念讲解】老师口吻解释关键技术:

  • 缓存策略:缓存是数据库的前置缓存层,存储热点数据(如热门车次、票价),查询时先从缓存获取,若缓存无则查库并更新。需解决雪崩(随机过期)、击穿(互斥锁/预加载)。
  • 读写分离:主库负责写(如订单插入),从库负责读(如车次查询),通过binlog同步主库数据,适用于读多写少场景。
  • 分库分表:水平拆分(按地区/业务模块),如北京车次表存入db_beijing;垂直拆分(按字段),如车次表拆分为基础表和票务表。全局ID(如Snowflake生成的订单ID)解决跨表关联,订单表通过订单ID关联车次表。跨库查询时,通过缓存聚合(预加载热门车次与订单关联数据)减少跨库操作。
  • 索引优化:为高频查询字段(如车次号、日期、用户ID)创建复合索引,如查询“北京到上海2024-01-01的车次”时,创建(出发地,目的地,日期)的复合索引。需分析查询模式,避免过度索引(写操作占比高时删除冗余索引),定期用EXPLAIN评估。

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) 【追问清单】及回答要点:

  • 问题1:缓存如何解决“缓存击穿”问题?
    回答:用互斥锁(如Redis的SETNX)或预加载热点数据,避免大量请求同时击穿缓存。
  • 问题2:分库分表后,如何处理跨表关联(如查询订单时关联车次信息)?
    回答:采用全局唯一ID(如雪花算法生成的订单ID关联车次ID),或引入中间表(订单-车次关联表),通过分布式事务(如两阶段提交)或最终一致性保证数据一致性。
  • 问题3:读写分离中,从库数据如何保证与主库一致?
    回答:通过MySQL的binlog日志同步主库数据,或使用主从复制机制,确保从库数据实时同步。
  • 问题4:索引优化中,如何避免“过度索引”导致写性能下降?
    回答:分析查询模式,仅对高频查询字段建索引,定期执行EXPLAIN分析查询计划,评估索引效果,必要时删除冗余索引。
  • 问题5:高并发下,缓存“雪崩”的应对措施?
    回答:设置缓存过期时间随机化(如±10%的随机偏移),或使用缓存分级(Redis+Memcached),热点数据预加载(提前加载热门车次信息到缓存)。

7) 【常见坑/雷区】

  • 仅单一技术(如只说缓存,忽略读写分离、分库分表),未体现组合优化,缺乏针对性。
  • 缓存策略未考虑热点数据预加载或缓存过期策略,导致缓存失效后大量请求冲击数据库。
  • 分库分表后未解决跨表关联复杂问题,导致查询效率下降,如订单表与车次表分库后,关联查询需跨库操作,增加延迟。
  • 读写分离未考虑数据一致性,导致从库数据与主库不一致,影响读数据准确性。
  • 索引优化过度,为所有字段建索引,导致写操作成本过高,反而影响系统性能,需平衡查询与写性能。
51mee.com致力于为招聘者提供最新、最全的招聘信息。AI智能解析岗位要求,聚合全网优质机会。
产品招聘中心面经会员专区简历解析Resume API
联系我们南京浅度求索科技有限公司admin@51mee.com
联系客服
51mee客服微信二维码 - 扫码添加客服获取帮助
© 2025 南京浅度求索科技有限公司. All rights reserved.
公安备案图标苏公网安备32010602012192号苏ICP备2025178433号-1