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

设计一个支持百万级订单峰值处理的贸易交易系统,请阐述核心架构设计思路,包括服务拆分、消息队列、缓存、数据库分库分表等关键组件的选择与设计,并说明如何保证系统的高可用性和低延迟。

南光(集团)有限公司信息技术类难度:中等

答案

1) 【一句话结论】
针对百万级订单峰值,核心架构通过微服务拆分实现业务解耦,采用异步消息队列(如Kafka)解耦订单与库存服务,结合分布式缓存(Redis)加速热点数据访问,数据库分库分表(按订单ID哈希分库、按月分表)缓解数据压力,并辅以负载均衡、熔断降级、多机房部署等高可用策略,确保系统高并发、低延迟、高可用。

2) 【原理/概念讲解】

  • 服务拆分:将交易系统拆为订单服务、库存服务、支付服务等微服务,通过API网关统一入口。核心是订单创建与库存扣减的解耦,避免订单服务阻塞。订单服务创建订单后,通过消息队列异步通知库存服务扣减库存,采用Saga模式(包含补偿事务)保证最终一致性。
  • 消息队列(Kafka):用于高吞吐异步消息传递,采用日志持久化(写入磁盘),多副本备份(如3副本),消息确认机制(生产者ACK+消费者ACK),确保消息不丢失。同时通过消息唯一标识(订单ID+时间戳)+幂等性检查,避免重复消费(如库存扣减重复执行)。
  • 分布式缓存(Redis集群):缓存订单状态、用户信息等热点数据,减少数据库压力。针对缓存问题:
    • 雪崩:随机过期时间或预加载热点数据;
    • 击穿:互斥锁+缓存(热点数据查询时加锁,避免热点数据同时查询数据库);
    • 穿透:布隆过滤器+空对象缓存(过滤无效请求,缓存空结果)。
  • 数据库分库分表:订单表按订单ID哈希分库(如10个库),按月分表(如每月新增数据分到新表),解决数据量过大。分片键选择(订单ID哈希+时间分片),避免数据倾斜;跨库事务采用Saga模式(失败时补偿,避免两阶段提交阻塞)。

3) 【对比与适用场景】

  • 消息队列(Kafka vs RabbitMQ)

    特性/组件KafkaRabbitMQ
    持久化日志存储磁盘,消息持久化支持持久化,默认非持久化
    副本机制多副本备份(3副本),高可用队列模型,副本较少
    消息确认生产者ACK+消费者ACK(确保不丢失)生产者ACK,消费者可选
    幂等性支持需手动实现(消息唯一ID+重试)需手动实现(消息唯一ID+重试)
    使用场景实时数据处理、日志收集、高吞吐异步微服务解耦、任务队列、消息模式多样
    注意点需管理消息重试逻辑,避免循环需配置持久化策略,避免消息丢失
  • 数据库分库分表(垂直分库 vs 水平分表)

    方式垂直分库水平分表
    定义按业务模块拆分数据库(如订单库、用户库)按数据量或时间拆分表(如订单表按月分表)
    分片键业务模块(订单库、用户库)时间(月)、ID(订单ID按月分表)
    跨库事务复杂(需分布式事务,如Saga)表间关联复杂,需路由
    数据倾斜可能(订单库负载不均)可能(分表后数据分布不均)
    使用场景业务模块独立,数据量不大单表数据量过大(如订单表百万级)
    注意点需跨库事务解决方案(Saga更推荐)需表级路由,避免数据倾斜

4) 【示例】(订单创建流程伪代码,含幂等性处理)

1. 客户端调用订单服务创建订单(POST /orders,参数:用户ID、商品ID、数量)
2. 订单服务验证用户信息(Redis缓存用户信息,若缓存未命中则查询数据库)
3. 订单服务查询商品库存(通过消息队列发送“查询库存”消息给库存服务)
4. 库存服务处理消息,返回库存是否充足(若充足,则扣减库存,并更新Redis缓存库存)
5. 库存服务发送“库存扣减完成”消息给订单服务
6. 订单服务消费消息,检查消息唯一标识(订单ID+时间戳),若已处理则跳过,否则确认库存扣减成功后,创建订单(写入数据库订单表,并更新Redis订单状态为“已创建”)
7. 订单服务返回订单创建结果(成功/失败)
8. 若库存扣减失败,库存服务发送“库存扣减失败”消息,订单服务通过Saga模式补偿:重试库存扣减或回滚订单(删除已创建订单,恢复库存)

5) 【面试口播版答案】
“面试官您好,针对百万级订单峰值,我设计的核心架构是微服务拆分+异步消息队列解耦+分布式缓存+数据库分库分表,并辅以高可用策略。首先,服务拆分:将系统拆为订单、库存、支付等微服务,通过API网关统一入口,订单创建与库存扣减解耦,避免阻塞。比如订单服务创建订单后,通过Kafka发送库存扣减消息,库存服务异步处理。其次,消息队列:用Kafka持久化存储,多副本备份,确保消息不丢失,同时通过消息唯一标识(订单ID+时间戳)保证幂等性,避免重复扣减库存。然后,分布式缓存:Redis集群缓存订单状态,订单创建后立即更新缓存,针对缓存雪崩用随机过期时间,击穿用互斥锁,穿透用布隆过滤器。接着,数据库分库分表:订单表按订单ID哈希分库(10个库),按月分表,解决数据量过大,同时通过动态分片调整负载。最后,高可用:Nginx负载均衡分发请求,Hystrix熔断降级,多机房部署(主备切换),保证系统稳定。这样能支撑百万级峰值,低延迟,高可用。”

6) 【追问清单】

  • 追问1:消息队列如何保证幂等性?
    回答要点:通过给消息添加唯一标识(订单ID+时间戳),消费时检查是否已处理过,若已处理则跳过,避免重复执行。
  • 追问2:订单创建后缓存如何保证一致性?
    回答要点:订单创建后立即更新Redis缓存(或设置TTL后失效),确保查询时获取最新状态。
  • 追问3:跨库事务补偿的具体步骤?
    回答要点:库存扣减失败时,订单服务通过Saga模式补偿,重试库存扣减或回滚订单(删除订单并恢复库存)。
  • 追问4:如何处理数据库分库分表后的数据倾斜?
    回答要点:采用订单ID哈希+时间分片,动态调整分片键,或根据负载情况调整分库数量。
  • 追问5:系统如何保证低延迟?
    回答要点:缓存加速热点数据,消息队列异步处理非实时任务,数据库读写分离,负载均衡优化请求分发。

7) 【常见坑/雷区】

  • 消息队列幂等性未处理:导致重复消费(如库存扣减重复执行),需通过消息唯一标识和重试机制解决。
  • 缓存未及时更新:订单创建后缓存未同步,导致查询错误,需立即更新缓存或使用缓存失效策略。
  • 数据库分库分表导致数据倾斜:哈希分库可能导致部分库负载过高,需选择合适的分片键(如订单ID哈希+时间分片)。
  • 高可用设计单一:仅依赖单机房,未考虑多机房容灾,需部署多机房(主备切换),结合负载均衡。
  • 服务拆分边界模糊:订单服务是否应包含库存扣减逻辑?正确做法是分离,避免强耦合。
51mee.com致力于为招聘者提供最新、最全的招聘信息。AI智能解析岗位要求,聚合全网优质机会。
产品招聘中心面经会员专区简历解析Resume API
联系我们南京浅度求索科技有限公司admin@51mee.com
联系客服
51mee客服微信二维码 - 扫码添加客服获取帮助
© 2025 南京浅度求索科技有限公司. All rights reserved.
公安备案图标苏公网安备32010602012192号苏ICP备2025178433号-1