缓存穿透:查询一个不存在的数据,mysql查询不到数据也不会直接写入缓存,就会导致每次请求都查数据库
解决方案一:缓存空数据,查询返回数据为空,仍把这个结果缓存
优点:简单
缺点:消耗内存,可能发生不一致问题
解决方案二:布隆过滤器(拦截不存在的数据)
请求来时先查询布隆过滤器,如果存在,查询redis;如果不存在,则会直接返回。(缓存预热时,预热布隆过滤器)
优点:内存占用较少,没有多余key
缺点:实现复杂,存在误判
布隆过滤器
bitmap(位图):相当于是一个以(bit)位为单位的数组,数组中每个单元只能存储二进制数0或1;
布隆过滤器作用:布隆过滤器可以用于检索一个元素是否存在一个集合中。
存储数据时:比如id为1的数据,通过多个hash函数获取hash值,根据hash计算数组对应位置改为1;
查询数据:使用相同的hash函数获取hash值,判断对应的位置是否都为1;都为1说明这个数是存在的,如果有一个不为1,则这个数不存在
误判率:数组越小误判率越大,数组越大误判率越小,但是带来了更多内存消耗。
缓存击穿:给某一个key设置过期时间,当key过期时候,恰好这个时间点对于key有大量并发请求过来,这些并发请求可能会瞬间把数据库压垮;
有人说,我们不是要把数据库数据同步到redis中,在数据同步到redis过程中,花费了过多的时间,在这期间,有大量并发请求。(多表统计花费时间更多)
解决方案一:互斥锁(强一致、性能差)
当线程一查询数据时,获取互斥锁,同步redis数据,写入缓存;这是进来线程二,获取互斥锁失败后,休眠一会在重试;线程一写入缓存完毕后,线程二就可以在redis中取到数据
解决方案二:逻辑过期(不设置过期时间、高可用、性能优,但是可能拿到不是最新数据)
不能保证数据绝对一致,先返回过期数据在同步数据库
缓存雪崩:指同一时间段大量的缓存key同时失效或者redis服务宕机,导致大量请求到达数据库
解决方案:
给不同的key设置不同的过期时间 ,添加随机值
利用redis集群提高服务可用性 哨兵模式、集群模式
给缓存业务添加降级,限流策略 nginx或spring cloud gateway
给业务添加多级缓存 caffeine