缓存穿透

出现原因

缓存穿透是指客户端查询一个根本不存在的数据(redis缓存和数据库中都不会存在)。缓存穿透将导致每次查询都穿过我们的缓存层直接到达数据库,对我们的数据库造成极大压力,而缓存层也失去了保护后端数据库的意义。造成其的主要原因如下:

  1. 代码或者数据出现问题;
  2. 恶意攻击;

解决方案:布隆过滤器

我看网上解决方案有的建议将空对象存到redis,这样虽然可以减轻数据库压力,但是在面对恶意攻击,上千万访问量的时候,无疑是增加了redis的压力,所以建议使用布隆过滤器来解决。

使用方式

1.maven中加入依赖

<dependency>
	<groupId>com.google.guava</groupId>
	<artifactId>guava</artifactId>
	<version>22.0</version>
</dependency>

2.代码

public String bloomSetKeyDemo() {

    String key = "bloomKey";
    String value = "bloomValue";

    boolean result = bloomFilter.put(key);

    if (!result) {
        return "fail";
    }
    stringRedisTemplate.opsForValue().set(key, value);
    return "done";
}


public String bloomGetKeyDemo() {
    String key = "bloomKey";
    boolean exist = bloomFilter.mightContain(key);

    if (!exist) {
        return "not exist ";
    }
    return stringRedisTemplate.opsForValue().get(key);

}

布隆过滤器原理:

布隆过滤器可以看成是一个很大的数组,数组中只有0 和1两个值。在我们向布隆过滤器添加key的时候,他会听过一些hash算法得到一个数值,然后用这个数据对布隆过滤器的数组长度进行取模,得到的值是多少就在数组角标处设为1。

比如:

key=a

数组长度为8

hash值=10

10%8=2

数组的2出标记为1

怎样防止redis穿透_缓存

当下次我们取值的时候,就可以判断弄一下a是否在布隆过滤器中,如果在说明可能存在此key,如果不在,则说明一定没缓存此key

缓存失效

由于大批量缓存在同一时间失效可能导致大量请求同时穿透缓存直达数据库,可能会造成数据库瞬间压力过大甚至挂掉。

解决方案

对同一批数据,在设置超时时间的时候,设置一点的差异。

缓存雪崩

缓存雪崩指的是宕掉后, 所有的请求直接请求到我们的后端服务器或者数据库。导致我们的后端服务器因承受不了过载请求而宕机。

解决方案

  1. 保证集群服务的高可用,使用redis集群方式
  2. 对服务进行限流,降级。比如使用hystrix(具体使用代码可以参照git地址:https://github.com/zhangshilin9527/fegin-hystrix-study
  3. 提前预防,在预知到某些大型活动来临之前,做一些方案,比如增加临时机器等。