缓存穿透是指 查询一个不存在的数据,每次都需要查询数据库。由于写入缓存是被动操作,并且数据库每次查询为空,所以不会向缓存中写入数据,导致每次查询会越过缓存直接查询数据库,访问量大时增加数据库压力
解决方案:
1、回写空值:
查询完数据库时,将空值塞入缓存并加入较短的过期时间。需要评估一下缓存容量是否能够支撑。如果需要大量的缓存节点来支持,那么就无法通过通过回种空值的方式来解决
2、布隆过滤器:
布隆过滤器位于缓存之前,请求先过布隆过滤器,若存在则访问缓存。
布隆过滤器查询出不存在则一定不存在,查询出存在有一定误判,可能不存在,主要与hash碰撞有关
布隆过滤器拥有极高的性能,无论是写入操作还是读取操作,时间复杂度都是 O(1) 是常量值。
不过任何事物都有两面性,布隆过滤器也不例外,它主要有两个缺陷:1. 它在判断元素是否在集合中时是有一定错误几率的,比如它会把不是集合中的元素判断为处在集合中;2. 不支持删除元素。关于第一个缺陷,主要是 Hash 算法的问题。因为布隆过滤器是由一个二进制数组和一个 Hash 算法组成的,Hash 算法存在着一定的碰撞几率。Hash 碰撞的含义是不同的输入值经过 Hash 运算后得到了相同的 Hash 结果。
3、后台定时任务塞入缓存:
某一个热点缓存项失效之后启动一个后台线程,穿透到数据库,将数据加载到缓存中,在缓存未加载之前,所有访问这个缓存的请求都不再穿透而直接返回。