
1) 【一句话结论】采用“分布式锁+消息队列+最终一致性补偿+缓存双写”架构,通过Redis分布式锁保证并发写入原子性,Kafka消息队列实现实时库存更新,结合缓存预热、版本号机制确保数据一致性,最终通过定时重试或消息重发补偿机制,减少不一致时间,支持高并发实时更新。
2) 【原理/概念讲解】老师讲解库存系统的高并发需求:生产线加工大豆后需实时减少库存,但多个生产线并发操作时,库存数据可能冲突。分布式系统下,数据不一致是核心挑战。
SETNX,用于保证并发写入的原子性,确保同一时间只有一个生产线能更新库存,避免冲突。锁粒度按产品ID划分(如锁key为inventory_lock:product_id),锁过期时间设为业务处理时间+缓冲(如10秒业务处理,锁设12秒),结合超时重试避免死锁。3) 【对比与适用场景】
| 方案 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| 最终一致性 | 系统在一段时间后达到一致状态 | 延迟一致性,允许临时不一致 | 高并发场景(如电商库存、生产系统) | 需要补偿机制(定时重试、消息重发) |
| 强一致性 | 系统立即响应所有操作,数据一致 | 立即一致,但可能牺牲性能 | 金融交易、核心业务(如银行转账) | 高并发下性能差,不适合大规模系统 |
4) 【示例】
def reduce_inventory(product_id, quantity):
lock_key = f"inventory_lock:{product_id}"
# 获取分布式锁,超时重试
with redis_lock(lock_key, timeout=12, retry=3, backoff=2):
cur_stock = get_stock_from_db(product_id)
if cur_stock < quantity:
raise ValueError("库存不足")
new_stock = cur_stock - quantity
# 更新数据库
update_stock(product_id, new_stock)
# 发送消息到Kafka
kafka_producer.send("inventory_update",
value={"product_id": product_id,
"quantity": quantity,
"new_stock": new_stock})
def query_inventory(product_id):
# 优先查缓存
stock = get_stock_from_cache(product_id)
if stock is None:
# 缓存未命中,查数据库
stock = get_stock_from_db(product_id)
# 缓存预热(设置TTL,如300秒)
set_cache(product_id, stock, ttl=300)
return stock
def consume_inventory_update():
for msg in kafka_consumer.poll(timeout_ms=100):
data = msg.value.decode()
product_id = data["product_id"]
new_stock = data["new_stock"]
# 更新本地缓存(或数据库,若缓存失效)
update_local_cache(product_id, new_stock)
5) 【面试口播版答案】
“面试官您好,针对9377公司大豆加工生产线的库存管理系统,我设计的方案核心是采用分布式架构,结合Redis分布式锁保证并发写入的原子性,通过Kafka消息队列实现实时库存更新,并采用最终一致性模型,结合缓存策略确保数据一致性。具体来说,生产线减少库存时,先获取分布式锁(锁key为产品ID,过期时间略长于业务处理时间,比如12秒),确保同一时间只有一个生产线能更新库存,避免并发冲突。更新后,通过Kafka发送库存更新消息,通知订单系统等下游服务。订单系统查询库存时,优先从缓存获取(缓存TTL设为5分钟),缓存未命中则查询数据库。对于临时不一致的情况,比如消息延迟或缓存过期,通过消息队列的重试机制(如Kafka自动重试)和缓存预热,确保最终数据一致。这样既能支持高并发实时更新,又能保证数据最终一致性,减少不一致时间。”
6) 【追问清单】
7) 【常见坑/雷区】