MST

星途 面试题库

面试题:缓存设计之在线教育平台缓存数据更新策略

在在线教育平台中,假设课程信息经常会有更新操作,同时为了应对高并发,使用了缓存。请阐述你会采用何种缓存数据更新策略,以确保缓存与数据库数据的一致性,并且尽量减少高并发场景下的缓存击穿、缓存雪崩问题。
31.6万 热度难度
后端开发缓存设计

知识考点

AI 面试

面试题答案

一键面试

缓存数据更新策略

  1. Cache-Aside Pattern(旁路缓存模式)
    • 读操作
      • 首先从缓存中读取课程信息。如果缓存命中,直接返回缓存中的数据。
      • 如果缓存未命中,从数据库中读取课程信息,然后将读取到的数据放入缓存,并返回给调用方。
    • 写操作
      • 先更新数据库中的课程信息。
      • 然后删除对应的缓存数据。这样下次读取时,会重新从数据库加载最新数据到缓存。此方法简单直观,能保证数据一致性,因为缓存删除操作相对更新操作更简单和可靠,减少了缓存与数据库数据不一致的窗口。
  2. Write - Through Pattern(写穿透模式)
    • 写操作
      • 同时更新数据库和缓存中的课程信息。确保数据库和缓存的数据立即保持一致。为了提高写操作的性能,可以采用批量写的方式,减少数据库和缓存的写次数。例如,收集多个课程更新操作,批量写入数据库和缓存。
      • 在高并发场景下,可能需要对写操作进行排队处理,防止大量写操作同时冲击数据库和缓存。可以使用消息队列(如 Kafka),将写请求发送到队列,由队列消费者依次处理更新数据库和缓存的操作。
    • 读操作:直接从缓存读取数据,如果缓存未命中,从数据库读取并更新缓存。
  3. Write - Behind Caching Pattern(写回缓存模式)
    • 写操作
      • 只更新缓存中的课程信息,标记缓存数据为脏数据。然后由专门的异步线程或任务,在合适的时机(例如缓存数据积累到一定数量,或者达到一定时间间隔)将脏数据批量更新到数据库。
      • 为了防止在异步更新到数据库之前系统崩溃导致数据丢失,可以采用持久化缓存(如 Redis 的 AOF 或 RDB 持久化机制)。同时,系统重启时,需要检查缓存中的脏数据并进行恢复更新到数据库。
    • 读操作:优先从缓存读取数据。如果缓存未命中,从数据库读取并更新缓存。

应对缓存击穿和缓存雪崩问题

  1. 应对缓存击穿
    • 使用互斥锁:在缓存未命中时,使用互斥锁(如 Redis 的 SETNX 命令实现分布式锁)。只有获取到锁的线程可以从数据库读取数据并更新缓存,其他线程等待。这样可以防止大量并发请求同时查询数据库。例如,在 Java 中可以使用 Redisson 等库实现分布式锁。
    • 设置热点数据永不过期:对于一些热点课程信息,设置缓存永不过期,同时可以在缓存数据中加入版本号或者时间戳,当数据库数据更新时,通过更新缓存中的版本号等方式,通知应用程序重新加载数据。
  2. 应对缓存雪崩
    • 分散过期时间:避免大量课程缓存设置相同的过期时间。可以在设置缓存过期时间时,加上一个随机值。例如,原本设置缓存过期时间为 60 分钟,可以改为 55 - 65 分钟之间的随机值,这样可以分散缓存过期的时间点,避免大量缓存同时过期。
    • 使用二级缓存:采用主缓存和二级缓存的架构。主缓存失效时,从二级缓存读取数据。二级缓存可以设置较长的过期时间或者永不过期。例如,主缓存使用 Redis,二级缓存可以使用本地缓存(如 Guava Cache)。
    • 搭建缓存集群:采用分布式缓存集群(如 Redis Cluster),提高缓存的可用性。即使部分缓存节点失效,其他节点仍能提供服务。同时,对缓存集群进行监控和自动故障转移,确保系统的稳定性。