面试题答案
一键面试实现思路
- Redis预扣库存:
- 利用Redis的原子操作,如
decr
命令。在收到扣减库存请求时,先在Redis中对商品库存进行扣减。例如,假设有商品ID为product:1
,库存初始值为100,当请求到达,执行decr product:1
,如果返回值大于等于0,说明预扣库存成功;如果返回值小于0,说明库存不足,直接返回库存不足的响应给客户端,不再进行后续数据库操作。
- 利用Redis的原子操作,如
- 数据库异步更新:
- 对于预扣库存成功的请求,将扣减库存的操作封装成消息发送到消息队列(如Kafka)。消息中包含商品ID、扣减数量等关键信息。
- 有一个独立的消费者服务监听消息队列,从队列中获取扣减库存消息,然后开启数据库事务进行库存更新。例如,在MySQL中,使用
START TRANSACTION
开启事务,执行UPDATE products SET stock = stock - {quantity} WHERE product_id = {product_id} AND stock >= {quantity}
语句,如果更新的行数大于0,说明数据库库存扣减成功,执行COMMIT
提交事务;如果更新行数为0,说明库存不足,执行ROLLBACK
回滚事务,并将库存恢复到Redis中的值(可通过incr
命令)。
- 缓存一致性处理:
- 当数据库库存更新成功后,需要更新Redis中的库存值,保证缓存和数据库的一致性。可以通过直接在Redis中设置新的库存值来实现,例如
SET product:1 {new_stock}
。 - 为了防止消息队列消费失败等异常情况,定期(如每隔一定时间)检查Redis和数据库库存的一致性。可以通过计算数据库中库存总量与Redis中库存总量进行对比,如果不一致,根据实际业务逻辑进行修复(如以数据库为准更新Redis)。
- 当数据库库存更新成功后,需要更新Redis中的库存值,保证缓存和数据库的一致性。可以通过直接在Redis中设置新的库存值来实现,例如
关键技术点
- Redis原子操作:
- 利用Redis单线程模型保证原子操作的一致性。
decr
等命令在高并发场景下能确保库存扣减的准确性,避免竞争条件。
- 利用Redis单线程模型保证原子操作的一致性。
- 消息队列:
- 消息队列的使用要保证高可用性和消息不丢失。例如在Kafka中,通过设置合适的副本因子和ISR(In - Sync Replicas)策略来确保消息的可靠传递。同时,要处理好消息的重复消费问题,如在数据库更新操作中采用幂等性设计,即多次执行相同的扣减库存操作结果相同。
- 数据库事务:
- 在数据库事务中,要注意锁的使用。例如在MySQL中,使用行锁(通过
UPDATE... WHERE...
语句中的条件来锁定具体行),避免锁表造成的性能瓶颈。同时,合理设置事务的隔离级别,如采用READ COMMITTED
隔离级别,既能保证读取已提交的数据,又能减少锁争用。
- 在数据库事务中,要注意锁的使用。例如在MySQL中,使用行锁(通过
- 缓存更新策略:
- 选择合适的缓存更新时机,既要保证数据库更新成功后及时更新缓存,又要避免在事务未提交时更新缓存导致数据不一致。同时,在处理缓存一致性检查时,要高效地获取数据库和Redis中的库存数据,可通过建立合适的索引等方式提高查询性能。