MST
星途 面试题库

面试题:缓存设计之缓存与持久化存储基本策略

在后端开发中,假设你负责一个电商产品详情页的缓存设计,产品数据存储在关系型数据库(如MySQL)中,简述如何设计缓存策略来平衡缓存与持久化存储,以提高页面加载速度并保证数据一致性,同时说明可能遇到的缓存失效问题及解决方案。
36.8万 热度难度
后端开发缓存设计

知识考点

AI 面试

面试题答案

一键面试

缓存策略设计

  1. 读写策略
    • 读策略
      • 首先尝试从缓存中读取产品详情数据。如果缓存命中,直接返回缓存中的数据,这样可以极大提高页面加载速度。
      • 如果缓存未命中,从MySQL数据库中读取数据。读取成功后,将数据存入缓存,以便后续请求能直接从缓存获取。
    • 写策略
      • 当产品数据在MySQL数据库更新后,同时更新缓存中的数据,保证缓存与数据库的数据一致性。
      • 可以采用双写操作,先写数据库,成功后再写缓存。但要注意可能出现写数据库成功,写缓存失败的情况,需要有重试机制或补偿措施。
  2. 缓存数据结构
    • 可以使用键值对(Key - Value)结构,以产品ID作为键,产品详情数据作为值。例如在Redis中,可以使用SET product_id json_string的方式存储,其中json_string是序列化后的产品详情数据。
  3. 缓存粒度
    • 细粒度缓存:可以按产品的不同属性或模块进行缓存,比如将产品基本信息、产品图片信息、产品评论信息等分开缓存。这样在部分数据更新时,只需要更新对应的缓存部分,而不需要更新整个产品详情缓存,减少缓存更新的开销。
    • 粗粒度缓存:直接缓存整个产品详情数据,优点是实现简单,读取时一次操作即可获取全部数据,但更新时可能会造成不必要的缓存更新。可以根据实际业务情况选择合适的粒度,或者结合使用。

缓存失效问题及解决方案

  1. 缓存穿透
    • 问题描述:查询一个不存在的数据,每次都绕过缓存直接查询数据库,大量这样的请求会对数据库造成压力。
    • 解决方案
      • 布隆过滤器:在缓存之前使用布隆过滤器。将数据库中存在的产品ID都添加到布隆过滤器中,当查询时,先经过布隆过滤器判断。如果布隆过滤器判断不存在,直接返回,不再查询数据库;如果判断存在,再查询缓存和数据库。
      • 空值缓存:当查询数据库发现数据不存在时,也将这个查询结果(空值)缓存起来,并设置一个较短的过期时间,防止缓存穿透。
  2. 缓存雪崩
    • 问题描述:大量缓存同时过期,导致大量请求直接查询数据库,可能使数据库压力过大甚至崩溃。
    • 解决方案
      • 设置随机过期时间:在设置缓存过期时间时,不要设置统一的过期时间,而是在一个合理范围内设置随机过期时间。例如原本设置缓存过期时间为1小时,可以改为在50分钟到70分钟之间随机设置过期时间,避免大量缓存同时过期。
      • 热点数据不过期:对于一些频繁访问的热点产品数据,不设置过期时间,而是通过其他机制(如数据库数据变更时主动更新缓存)保证数据一致性。
  3. 缓存击穿
    • 问题描述:一个热点数据在缓存过期的瞬间,大量请求同时访问,这些请求都会绕过缓存直接查询数据库,对数据库造成较大压力。
    • 解决方案
      • 互斥锁:在缓存过期时,使用互斥锁(如Redis的SETNX命令)来保证只有一个请求能去查询数据库并更新缓存,其他请求等待。获取锁的请求查询数据库后更新缓存,然后释放锁,其他等待的请求就可以从缓存中获取数据。
      • 二级缓存:使用二级缓存,比如一个短时间过期的一级缓存和一个长时间过期的二级缓存。当一级缓存过期时,先从二级缓存获取数据,同时后台异步更新一级缓存,这样可以避免大量请求直接查询数据库。