面试题答案
一键面试设计思路
- 缓存系统:
- 作用:用于快速响应用户请求,减轻数据库压力。在秒杀开始前,将商品库存数据加载到缓存中,如使用Redis。用户请求到达时,先从缓存中获取库存信息并判断是否可购买。
- 选择原因:Redis具有高并发读写性能,支持原子操作,适合处理库存扣减这类对数据一致性和并发性能要求高的场景。
- 消息中间件:
- 作用:用于异步处理实际的库存扣减操作,确保最终一致性。当缓存中库存扣减成功后,发送消息到消息中间件,由消费者从消息中间件获取消息,进行数据库层面的库存扣减。
- 选择原因:消息中间件(如Kafka、RabbitMQ等)可以削峰填谷,将高并发的库存扣减请求转化为顺序消费,避免数据库瞬间高负载,同时保证消息的可靠传递。
关键步骤
- 初始化阶段:
- 缓存预热:在秒杀活动开始前,将商品库存信息加载到Redis缓存中,设置合适的过期时间。例如,使用Redis的SET命令设置库存数量,如
SET product:1:stock 100
(假设商品ID为1,初始库存100)。 - 消息中间件初始化:创建库存扣减相关的队列或主题,配置消息生产者和消费者。例如,在RabbitMQ中创建一个名为
product_stock_deduction
的队列。
- 缓存预热:在秒杀活动开始前,将商品库存信息加载到Redis缓存中,设置合适的过期时间。例如,使用Redis的SET命令设置库存数量,如
- 用户抢购阶段:
- 缓存扣减:用户发起抢购请求,系统先从Redis中获取库存信息,使用
GET product:1:stock
获取库存数量。然后通过Redis的原子操作(如DECR product:1:stock
)进行库存扣减。如果扣减后库存数量大于等于0,表明抢购成功,继续后续流程;否则,返回库存不足的提示。 - 消息发送:抢购成功后,将库存扣减的消息发送到消息中间件。消息内容可包含商品ID、用户ID等关键信息,如
{"product_id": 1, "user_id": 1001}
。
- 缓存扣减:用户发起抢购请求,系统先从Redis中获取库存信息,使用
- 库存持久化阶段:
- 消息消费:消息中间件的消费者从队列或主题中获取库存扣减消息,根据消息内容进行数据库层面的库存扣减操作。例如,在MySQL数据库中执行
UPDATE products SET stock = stock - 1 WHERE product_id = 1 AND stock > 0
语句,同时可添加事务保证数据一致性。 - 异常处理:如果在数据库库存扣减过程中出现异常,如数据库连接失败等,可将消息重新放回消息中间件,进行重试,确保库存扣减操作最终成功,防止超卖。同时,在缓存中记录重试标识,避免重复发送相同消息导致多次扣减库存。
- 消息消费:消息中间件的消费者从队列或主题中获取库存扣减消息,根据消息内容进行数据库层面的库存扣减操作。例如,在MySQL数据库中执行