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

设计一个支持百万级QPS的电商订单系统,需考虑高并发、分布式、容错性,请从微服务拆分、缓存策略、数据库分库分表、消息队列等方面阐述系统架构设计。

淘天集团T-STAR 日常实习生难度:困难

答案

1) 【一句话结论】
为支撑百万级QPS的电商订单系统,需通过微服务拆分(订单、库存、支付等)、订单业务状态机管理状态流转、分布式缓存(Redis)结合随机过期时间防雪崩、数据库分库分表(哈希分库+时间分表)、消息队列(Kafka)实现异步解耦与可靠性保障,构建高并发、容错的订单系统。

2) 【原理/概念讲解】

  • 微服务拆分:将订单系统拆分为订单服务(核心,负责订单创建、查询、状态管理)、库存服务(库存扣减)、支付服务(支付处理)、物流服务等。每个服务独立部署,通过API网关统一入口,类比“搭积木”——每个模块只负责单一职责,高并发时压力分散(如订单服务只处理订单逻辑,库存服务只处理库存逻辑,避免职责交叉导致性能瓶颈)。
  • 订单业务状态机:定义订单状态(待支付、已支付、已发货、已取消等),状态流转由事件驱动(如订单创建→待支付,支付成功→已支付,物流发货→已发货)。各服务通过消息队列或事件通知同步状态,避免状态不一致(例如订单服务发送“订单创建”事件,库存服务消费后更新库存并同步订单状态)。
  • 分布式缓存(Redis):使用Redis集群缓存订单数据(如订单ID→订单对象)和热点商品信息,查询时优先从缓存获取,减少数据库压力(如订单创建时,先写入数据库,再写入Redis;查询订单时,优先从Redis取,若缓存无则查询数据库)。为防缓存雪崩,设置每个订单key的过期时间为10秒,并随机偏移1-5秒(避免集中过期导致大量请求击穿数据库)。
  • 数据库分库分表:订单表按订单ID哈希分库(如订单ID%N取模分到不同数据库实例),按时间分表(每月新增一张表,如order_202401);订单表与订单商品表垂直分库(订单表放订单库,订单商品表放商品库),订单表按ID范围水平分表(如order_0-100000、order_100001-200000)。目的是避免单表数据量过大(如订单表百万级数据量),提升查询性能。
  • 消息队列(Kafka):作为异步通信中间件,解耦订单服务与库存、支付等服务。订单创建后发送消息到“库存扣减”队列,库存服务消费后执行库存扣减,即使库存服务暂时不可用,订单服务不会阻塞,保证高可用;消费失败后重试3次,失败后进入死信队列(DLQ),后续人工处理或重试。

3) 【对比与适用场景】

  • 业务状态机 vs 传统状态管理
    | 对比项 | 业务状态机 | 传统状态管理 | |---|---|---| | 定义 | 状态流转由事件驱动,状态机模型管理状态 | 手动更新状态,无状态机模型 | | 特性 | 自动化状态流转,减少状态错误 | 需手动维护状态,易出错 | | 使用场景 | 需要复杂状态流转(如订单、物流) | 简单状态,状态较少 | | 注意点 | 状态机模型设计复杂,需考虑所有状态和事件 | 状态简单,维护成本低 |

  • 缓存雪崩解决方案
    | 解决方案 | 随机过期时间 | 分布式限流 | |---|---|---| | 定义 | 为每个缓存key设置随机过期时间(如10秒+1-5秒偏移) | 限制并发请求数(如令牌桶算法) | | 优点 | 避免集中过期,减少瞬时压力 | 控制请求速率,缓解雪崩 | | 缺点 | 可能导致缓存命中率降低(过期时间变长) | 请求延迟增加,用户体验下降 | | 适用场景 | 缓存数据量较大,对实时性要求高 | 请求量极大,需严格限流 |

4) 【示例】
用户下单流程(伪代码):

  1. 用户发起“下单”请求 → 订单服务接收
  2. 订单服务检查商品库存:先从Redis缓存获取(若缓存无,查询数据库),若库存充足
  3. 订单服务创建订单(写入数据库,同时写入Redis缓存,设置过期时间10秒+随机偏移1-5秒)
  4. 订单服务发送消息到“库存扣减”队列(Kafka主题:order_stock_decrease)
  5. 库存服务消费消息 → 执行库存扣减(更新数据库库存表)
  6. 库存服务发送“支付”消息到“支付”队列(Kafka主题:order_payment)
  7. 支付服务消费消息 → 执行支付(如支付宝/微信支付),若成功 → 发送“物流”消息到“物流”队列(Kafka主题:order_delivery)
  8. 物流服务消费消息 → 更新订单状态为“已发货”,并更新Redis缓存订单状态

5) 【面试口播版答案】
面试官好,针对百万级QPS的电商订单系统设计,核心是通过**微服务拆分+订单业务状态机+分布式缓存(防雪崩)+数据库分库分表+消息队列(解耦与可靠)**的组合,保障高并发与容错。首先,微服务拆分:订单、库存、支付等模块独立,比如订单服务只管订单创建,库存服务只管库存扣减,通过API网关聚合,压力分散。然后,订单业务状态机:定义状态(待支付、已支付、已发货等),事件驱动状态流转,比如订单创建后状态为“待支付”,支付成功后状态变为“已支付”,物流发货后变为“已发货”,各服务通过消息队列同步状态,避免状态不一致。接着,分布式缓存:Redis集群缓存订单数据,查询时优先缓存,为防雪崩,设置每个订单key的过期时间为10秒并随机偏移1-5秒。然后,数据库分库分表:订单表按订单ID哈希分库,按月分表,订单表与订单商品表垂直/水平分表,避免单表数据过大。最后,消息队列:Kafka作为异步通信中间件,订单创建后发送库存扣减消息,库存服务消费后扣减库存,消费失败后重试3次,失败后进入死信队列。整体架构通过这些组件协同,支撑百万级QPS,同时保障容错性。

6) 【追问清单】

  • 问题1:微服务拆分的边界如何确定?
    回答要点:根据业务职责单一性,比如订单服务只管订单创建、查询,库存服务只管库存扣减,避免职责交叉导致性能瓶颈。
  • 问题2:如何解决缓存雪崩问题?
    回答要点:设置缓存过期时间随机化(每个key的过期时间在基础值上随机偏移),避免集中过期导致数据库压力激增。
  • 问题3:消息队列的可靠性如何保障?
    回答要点:消息持久化存储(Kafka写入磁盘),消费端ACK确认,消费失败后重试3次,失败后进入死信队列(DLQ),用于后续处理。
  • 问题4:数据库分库分表后,跨库事务如何处理?
    回答要点:采用异步事务(最终一致性),通过消息队列通知其他服务更新数据,或使用分布式事务方案(如两阶段提交2PC,但需考虑性能)。
  • 问题5:系统如何保证缓存与数据库数据一致性?
    回答要点:双写策略(先写数据库,再写缓存),或使用数据库事务与缓存事务结合(确保原子性),或通过消息队列通知其他服务更新缓存。

7) 【常见坑/雷区】

  • 坑1:业务状态机设计不当,导致状态流转错误(如支付成功后状态未更新,导致订单状态异常)。
  • 坑2:缓存雪崩未解决,集中过期导致数据库瞬间压力过大,服务崩溃。
  • 坑3:消息队列积压,未设置重试机制或死信队列,导致消息丢失或处理失败。
  • 坑4:分库分表导致跨表查询复杂,未优化路由,影响查询性能。
  • 坑5:分布式锁使用不当,导致死锁(如库存扣减时锁超时,其他请求获取不到锁,或锁释放不及时)。
51mee.com致力于为招聘者提供最新、最全的招聘信息。AI智能解析岗位要求,聚合全网优质机会。
产品招聘中心面经会员专区简历解析Resume API
联系我们南京浅度求索科技有限公司admin@51mee.com
联系客服
51mee客服微信二维码 - 扫码添加客服获取帮助
© 2025 南京浅度求索科技有限公司. All rights reserved.
公安备案图标苏公网安备32010602012192号苏ICP备2025178433号-1