先解析一下Redis中什么叫做 缓存穿透 和 缓存击穿:
缓存穿透:首先我们要明确概念,缓存穿透是 在查询数据时 查询的数据在 redis 和 DB中都没有的 叫做缓穿透,解决方案,如果有这样的情况下 可以在第一次从DB中查询 判断结果是否为空 若为空 则直接 在redis中对应key的value存一个null 并且设置很短的过期时间
缓存击穿:Redis中没有 但DB中有;正常情况下我们查询同一条数据会先到Redis缓存中查取,如果没有再到数据库中查询,如果同一时间几千个用户查询同一条数据,在第一个线程到数据库中查询到了还未来得及更新到Redis里时剩下的线程也同时到数据库中查询,就无法体现Redis缓存的目的,这样被称为 Redis 缓存击穿,大批量请求直接到数据库中查询,很容易导致数据库直接奔溃。
我们看一下会导致 缓存击穿的代码:
redisConfig是我封装的一个类
请求到了这个service 先去的redis查询,查询不到才会去数据库查询,但是没有添加锁 故导致了 缓存击穿
@Overridepublic Student findStudent(String key) { long l1 = System.currentTimeMillis(); log.info("先去redis里面去取..."); Student student = (Student) redisConfig.get("student-"+key); if (null == student){ log.info("redis中没有查到,到数据库中去取..."); student = studentDao.getStudent(Integer.valueOf(key)); redisConfig.set("student-"+student.getId(),student); long l2 = System.currentTimeMillis(); log.info("l2-l1:{}",l2-l1); } long l3 = System.currentTimeMillis(); log.info("l3-l1:{}",l3-l1); return student;}# 我用Jmeter测试了一个高并发场景 从截图中可以看到 多个线程 多次到数据库中查询了
我们再看一下加了锁之后的代码: