缓存设计

缓存是系统设计中必不可少的一环,但很多时候缓存设计不当可能会导致一些问题,

比如:缓存穿透,是指每次查询,都走了从缓存,再穿透到DB这个过程,原因一般是数据在DB中不存在。一般的缓存使用流程是,先进行缓存查询,如果key不存在或者key已经过期,再对DB进行查询,并把查询到的对象,放进缓存。如果DB查询对象为空,则不放进缓存。如果查询一定不存在的对象,就会每次都去查询 DB,而每次查询都是空,每次又都不会进行缓存。假如有恶意攻击,就可以利用这个漏洞,对DB造成压力,甚至压垮DB。缓存设计时,应考虑缓存穿透保护,即针对缓存穿透问题采取有效措施,防止大量请求穿透缓存访问 DB 导致 DB 挂掉。

【最佳实践】

  1. 一般缓存使用,先进行缓存查询,如果 key 不存在或者 key 已经过期,再从 DB 进行查询,并把查询到的对象放进缓存;

    如果 DB 查询对象为空,也将空值写进缓存,只是设定的缓存过期时间较短,比如设置为 60 秒。当有新 key 产生的时候,对缓存进行清理。倘若请求为空的情况太多,导致缓存空数据占用内存空间太大,推荐使用布隆过滤器。即创建一个足够大的 bitmap,用于存储可能访问的 key,不存在的 key 直接被过滤。通过一致性 hash 来进行热点散列。

  2. 业务代码中,缓存层统一添加在数据层上,服务层下,禁止出现嵌套调用。

  3. 构建数据发生异常时,错误数据不放入缓存。
  4. 在任何需要远程调用的逻辑,都应该有恰当的缓存策略,特别是元数据的场景。