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

卫龙电商大促期间,订单系统需要实时扣减库存,请设计一个高并发库存更新方案,考虑分布式事务、缓存、数据库优化,并说明如何保证库存准确性。

卫龙研发类难度:中等

答案

1) 【一句话结论】:采用“缓存优先+异步落库+补偿机制”的分布式库存更新方案,通过Redis缓存降低数据库压力,异步落库保证数据持久化,结合TCC或Saga补偿确保库存最终一致性。

2) 【原理/概念讲解】:面试官您好,要解决高并发库存更新,核心是“分布式环境下的数据一致性”问题。因为订单和库存属于不同服务(订单服务负责下单,库存服务负责扣减),无法用单机事务(如数据库事务)来保证两者原子性,所以需要用“最终一致性”方案。

  • 缓存的作用:Redis作为缓存,存储商品库存数据(key为stock:goods_id,value为库存数量),因为Redis的原子操作(如DECR)能保证并发扣减安全,且响应速度远快于数据库,适合秒杀等高并发场景。
  • 数据库的作用:库存表(stock_table)存储持久化库存,通过索引(如goods_id索引)加速查询和更新。
  • 分布式事务的补偿机制:由于订单和库存不在同一事务,采用“先缓存后异步落库”的策略,即订单服务调用库存服务时,优先从缓存扣减库存(若缓存扣减成功,返回订单创建成功;若失败,返回库存不足)。之后,库存服务通过消息队列(如Kafka)异步将扣减操作写入数据库(更新库存表,减少数量)。如果异步落库失败,会触发补偿任务,重新执行扣减操作,确保最终库存与缓存一致。
  • 数据库优化:对库存表加乐观锁(如version字段),防止并发更新冲突;缓存加互斥锁(如Redis的SETNX),保证同一时间只有一个请求扣减库存,避免超卖。

3) 【对比与适用场景】:

方案定义特性使用场景注意点
先数据库后缓存订单扣减库存后,先更新数据库,再更新缓存数据库强一致性,缓存最终同步库存更新频率低,系统负载低可能导致缓存与数据库不一致,高并发下响应慢
先缓存后数据库(异步)订单扣减缓存库存,异步落库高并发下缓存响应快,数据库压力小秒杀、大促等高并发场景需要补偿机制保证最终一致性,缓存与数据库版本校验

4) 【示例】:
订单服务调用库存服务的流程(伪代码):

# 订单服务调用库存服务
def create_order(order_id, goods_id, quantity):
    stock_service = StockService()
    result = stock_service.deduct_stock(goods_id, quantity)
    if result == "success":
        order = Order(order_id, goods_id, quantity)
        order.save()
        return "order_created"
    else:
        return "stock_insufficient"

# 库存服务处理库存扣减
def deduct_stock(goods_id, quantity):
    stock = redis.get(f"stock:{goods_id}")
    if stock is None:
        stock = db.query_stock(goods_id)
        if stock is None:
            return "stock_not_found"
        redis.set(f"stock:{goods_id}", stock)  # 缓存预热
    current_stock = int(stock)
    if current_stock < quantity:
        return "stock_insufficient"
    
    new_stock = redis.decr(f"stock:{goods_id}", amount=quantity)
    if new_stock < 0:
        trigger_compensation(goods_id, quantity)
        return "stock_insufficient"
    
    async_task = AsyncTask(
        task_type="deduct_stock",
        goods_id=goods_id,
        quantity=quantity,
        new_stock=new_stock
    )
    async_task.send_to_kafka()
    
    return "success"

# 异步落库任务
def async_deduct_stock(goods_id, quantity, new_stock):
    try:
        db.update_stock(goods_id, new_stock)
    except Exception as e:
        log_error(e)
        trigger_compensation(goods_id, quantity)

5) 【面试口播版答案】:
面试官您好,针对高并发库存更新,我设计的方案核心是“缓存优先+异步落库+补偿机制”。首先,订单系统调用库存服务时,优先从Redis缓存查询库存,若缓存有数据且足够,直接用Redis的DECR命令扣减库存,这样响应快,能应对秒杀等场景。然后,通过消息队列(如Kafka)异步将扣减操作写入数据库,避免数据库压力过大。为了保证最终一致性,当缓存扣减失败或数据库写入失败时,会触发补偿任务,重新执行扣减操作。另外,数据库对库存表加乐观锁(version字段),防止并发更新冲突;缓存加互斥锁(Redis的SETNX),保证同一时间只有一个请求扣减库存。这样既能保证高并发下的性能,又能确保库存准确性。

6) 【追问清单】:

  1. 如果缓存扣减失败怎么办?
    回答:触发补偿任务,重新执行扣减操作,确保最终库存正确。
  2. 分布式事务怎么处理?
    回答:用TCC模式,比如准备(扣减缓存)、确认(落库成功)、取消(缓存加回)。
  3. 缓存雪崩怎么办?
    回答:设置合理的过期时间,或者用缓存预热,或者加互斥锁防止雪崩。
  4. 数据库优化措施?
    回答:索引优化(商品ID索引)、分库分表(如果库存量很大)、读写分离。
  5. 如何保证库存准确性?
    回答:通过补偿机制和最终一致性保证,比如异步落库失败后重试,缓存与数据库的版本校验。

7) 【常见坑/雷区】:

  1. 直接用数据库事务处理订单和库存,导致性能下降,因为订单和库存不在同一事务。
  2. 只用缓存,没有异步落库,导致缓存数据丢失,库存不准确。
  3. 缓存更新策略错误,比如先更新数据库再更新缓存,在高并发下导致缓存与数据库不一致。
  4. 没有考虑缓存穿透,比如空值缓存,导致库存查询失败。
  5. 分布式事务方案选择不当,比如两阶段提交太重,导致性能问题,而TCC或Saga更适合高并发场景。
51mee.com致力于为招聘者提供最新、最全的招聘信息。AI智能解析岗位要求,聚合全网优质机会。
产品招聘中心面经会员专区简历解析Resume API
联系我们南京浅度求索科技有限公司admin@51mee.com
联系客服
51mee客服微信二维码 - 扫码添加客服获取帮助
© 2025 南京浅度求索科技有限公司. All rights reserved.
公安备案图标苏公网安备32010602012192号苏ICP备2025178433号-1