面试题答案
一键面试缓存策略设计
- 读写策略
- 读策略:
- 首先尝试从缓存中读取产品详情数据。如果缓存命中,直接返回缓存中的数据,这样可以极大提高页面加载速度。
- 如果缓存未命中,从MySQL数据库中读取数据。读取成功后,将数据存入缓存,以便后续请求能直接从缓存获取。
- 写策略:
- 当产品数据在MySQL数据库更新后,同时更新缓存中的数据,保证缓存与数据库的数据一致性。
- 可以采用双写操作,先写数据库,成功后再写缓存。但要注意可能出现写数据库成功,写缓存失败的情况,需要有重试机制或补偿措施。
- 读策略:
- 缓存数据结构
- 可以使用键值对(Key - Value)结构,以产品ID作为键,产品详情数据作为值。例如在Redis中,可以使用
SET product_id json_string
的方式存储,其中json_string
是序列化后的产品详情数据。
- 可以使用键值对(Key - Value)结构,以产品ID作为键,产品详情数据作为值。例如在Redis中,可以使用
- 缓存粒度
- 细粒度缓存:可以按产品的不同属性或模块进行缓存,比如将产品基本信息、产品图片信息、产品评论信息等分开缓存。这样在部分数据更新时,只需要更新对应的缓存部分,而不需要更新整个产品详情缓存,减少缓存更新的开销。
- 粗粒度缓存:直接缓存整个产品详情数据,优点是实现简单,读取时一次操作即可获取全部数据,但更新时可能会造成不必要的缓存更新。可以根据实际业务情况选择合适的粒度,或者结合使用。
缓存失效问题及解决方案
- 缓存穿透
- 问题描述:查询一个不存在的数据,每次都绕过缓存直接查询数据库,大量这样的请求会对数据库造成压力。
- 解决方案:
- 布隆过滤器:在缓存之前使用布隆过滤器。将数据库中存在的产品ID都添加到布隆过滤器中,当查询时,先经过布隆过滤器判断。如果布隆过滤器判断不存在,直接返回,不再查询数据库;如果判断存在,再查询缓存和数据库。
- 空值缓存:当查询数据库发现数据不存在时,也将这个查询结果(空值)缓存起来,并设置一个较短的过期时间,防止缓存穿透。
- 缓存雪崩
- 问题描述:大量缓存同时过期,导致大量请求直接查询数据库,可能使数据库压力过大甚至崩溃。
- 解决方案:
- 设置随机过期时间:在设置缓存过期时间时,不要设置统一的过期时间,而是在一个合理范围内设置随机过期时间。例如原本设置缓存过期时间为1小时,可以改为在50分钟到70分钟之间随机设置过期时间,避免大量缓存同时过期。
- 热点数据不过期:对于一些频繁访问的热点产品数据,不设置过期时间,而是通过其他机制(如数据库数据变更时主动更新缓存)保证数据一致性。
- 缓存击穿
- 问题描述:一个热点数据在缓存过期的瞬间,大量请求同时访问,这些请求都会绕过缓存直接查询数据库,对数据库造成较大压力。
- 解决方案:
- 互斥锁:在缓存过期时,使用互斥锁(如Redis的SETNX命令)来保证只有一个请求能去查询数据库并更新缓存,其他请求等待。获取锁的请求查询数据库后更新缓存,然后释放锁,其他等待的请求就可以从缓存中获取数据。
- 二级缓存:使用二级缓存,比如一个短时间过期的一级缓存和一个长时间过期的二级缓存。当一级缓存过期时,先从二级缓存获取数据,同时后台异步更新一级缓存,这样可以避免大量请求直接查询数据库。