MST
星途 面试题库

面试题:缓存设计之专家难度:复杂业务场景下双写一致性解决方案设计

假设存在一个电商系统,商品库存数据需要在缓存与数据库间保持一致性,且存在高并发的扣减库存操作、库存查询操作以及库存批量更新操作,同时要考虑系统的可用性和性能。请设计一套完整的缓存与数据库双写一致性解决方案,并阐述方案中如何处理可能出现的并发冲突和异常情况。
47.4万 热度难度
后端开发缓存设计

知识考点

AI 面试

面试题答案

一键面试

1. 缓存与数据库双写一致性解决方案

读写策略

  • 读操作
    • 先从缓存读数据,如果缓存命中,直接返回数据。
    • 如果缓存未命中,从数据库读取数据,将数据写入缓存(设置合适的过期时间),然后返回数据。
  • 写操作
    • 先更新数据库,成功后再更新缓存。这种顺序可以避免先更新缓存,数据库更新失败导致数据不一致的情况。

缓存选型

选用如 Redis 这样高性能、支持丰富数据结构的缓存系统。Redis 具备高并发读写能力,适合处理电商系统的高并发操作。

批量更新操作

  • 对于库存批量更新操作,先将批量更新的数据进行整理,一次性更新数据库。数据库操作成功后,批量更新缓存。可以使用 Redis 的事务(MULTI - EXEC)功能确保缓存更新的原子性,防止部分更新成功部分失败的情况。

2. 并发冲突处理

扣减库存操作

  • 乐观锁:在数据库表中增加一个版本号字段。每次扣减库存前,先读取库存数据及版本号,扣减库存时带上版本号进行更新,并将版本号加 1。只有当数据库中的版本号与读取时一致时,更新才会成功,否则重试。
  • 分布式锁:使用 Redis 的 SETNX 命令实现分布式锁。在扣减库存操作前,先获取锁,操作完成后释放锁。这样可以保证同一时间只有一个线程能进行扣减库存操作,避免并发冲突。但要注意锁的过期时间设置,防止死锁。

库存查询与写操作并发

  • 读操作本身不会直接导致数据不一致,但高并发下可能读到脏数据。可以通过合理设置缓存过期时间,使缓存数据能及时更新。同时,在写操作完成后,主动刷新相关缓存数据,保证后续读操作能获取到最新数据。

3. 异常情况处理

数据库更新异常

  • 如果数据库更新失败,记录详细的错误日志,包括操作类型、商品信息、失败原因等。对于重要的更新操作,可以进行重试,设置合理的重试次数和重试间隔。如果多次重试仍失败,通知相关运维人员进行处理。

缓存更新异常

  • 缓存更新失败时,同样记录错误日志。可以考虑使用消息队列(如 Kafka)将更新缓存的任务重新发送到队列中,由专门的消费者进行重试,确保缓存最终能更新成功。同时,在系统中设置监控机制,对缓存更新失败的频率进行监控,当失败次数超过阈值时发出告警。