复习

  • Redis 数据类型 命令
    • string
    • list
    • hash
    • set
    • sorted set
  • redis使用规范
    • key设计 命名规范 ugc:user:1
    • value设计 避免BigKey
      • string长度 大小
    • 禁用命令
      • 怎么禁用 /etc/redis.conf rename-command flushdb “”
      • 禁用 时间复杂度 O(n) keys / flushdb / flushall /config
      • hgetall 谨慎使用
      • keys hgetall smembers => scan / hscan /zscan /sscan
      • scan 游标 match 模式 count 最大返回数量
  • Java连接Redis
    • jedis 将所有命令转换成方法
    • spring-data-redis
      • RedisTemplate
        • opsForXXX
        • boundXXXOps

image.png

Redis特性

缓存

  1. @GetMapping("/student/{id}")
  2. public Student find(@PathVariable("id")Integer id) throws ParseException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
  3. log.info("查找学生 :{}",id);
  4. if(id==null){
  5. return null;
  6. }
  7. Student student = null;
  8. //1. 从缓存中获取
  9. String stuKey= "stu:"+id;
  10. if(redisTemplate.hasKey(stuKey)){
  11. log.info("缓存中存在{},从缓存中获取",stuKey);
  12. BoundHashOperations ops = redisTemplate.boundHashOps(stuKey);
  13. //hash的所有字段,表示学生的所有信息
  14. Map<String,Object> entries = ops.entries();
  15. log.info("{}",entries);
  16. // //转换成student对象 反序列化
  17. student = new Student();
  18. student.setClassName((String) entries.get("className"));
  19. student.setStudentId(Integer.parseInt((String)entries.get("studentId")) );
  20. student.setStudentName((String) entries.get("studentName"));
  21. student.setStudentNo((String) entries.get("studentNo"));
  22. student.setGender((String) entries.get("gender"));
  23. student.setAge(Integer.parseInt((String) entries.get("age")));
  24. student.setMajor((String) entries.get("major"));
  25. //
  26. String registerTime = (String) entries.get(entries.get("registerTime"));
  27. // student.setRegisterTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(registerTime));
  28. student.setCounselor((String) entries.get("counselor"));
  29. // student = BeanUtils.mapToBean(entries, Student.class);
  30. // student = new Student();
  31. // BeanUtils.populate(student,entries);
  32. return student;
  33. }
  34. //2. 从数据库中查询
  35. log.info("查询数据库,id=",id);
  36. student = studentService.findById(id);
  37. //3. 加入到缓存中
  38. log.info("存入缓存中{}",student);
  39. BoundHashOperations ops = redisTemplate.boundHashOps(stuKey);
  40. Map<String, String> stringObjectMap = BeanUtils.describe(student);
  41. ops.putAll(stringObjectMap);
  42. redisTemplate.expire(stuKey,30, TimeUnit.MINUTES);
  43. return student;
  44. }
  1. 不够通用 2. 不够简洁

Spring 缓存抽象 spring cache abstraction
增 @Cachable
删 @CacheEvict
改 @CachePut

在application类上加 @EnableCaching

  1. @GetMapping("findById")
  2. @Cacheable(cacheNames = "stuCache",key="#stuId")
  3. public Student findById(int stuId){
  4. log.info("从数据库获取数据{}",stuId);
  5. return studentService.findById(stuId);
  6. }
  7. @PutMapping("updateStu")
  8. @CachePut(cacheNames = "stuCache",key = "#student.studentId")
  9. public Student updateStudent(@RequestBody Student student){
  10. studentService.update(student);
  11. return student;
  12. }
  13. @DeleteMapping("/deleteById")
  14. @CacheEvict(cacheNames = "stuCache",key = "#id")
  15. public void deleteStudent(int id){
  16. studentService.delById(id);
  17. }
  1. pom.xml必须要有redis的依赖, SpringCache 支持多种不同的缓存,其中包括内存缓存,如果没有redis依赖,则使用内存缓存
  2. 缓存对象,要求加Serializable接口
  3. 如何查看redis中的缓存? keys * string

    缓存配置

    1. spring:
    2. redis:
    3. host: localhost
    4. port: 6379
    5. cache:
    6. type: redis
    7. redis:
    8. time-to-live: 60M
    9. key-prefix: 'redisbootdemo::'

    缓存问题

    image.png
    缓存过期的作用=> 保证数据的一致性;减少内存空间;

缓存击穿:有一个key过期时,大量的查询该key的请求,透过redis进入到数据库,key是热点key

  • 时间点:在某个key过期 到 该key的缓存重新生成之间
  • 解决方案:在缓存过期后,请求加互斥锁

缓存穿透:大量查询不存在的key

  • 解决方案:缓存空值;布隆过滤器 BloomFilter(超大的位数组,每1位只有0和1可以表示是否存在)

缓存雪崩:多个key在同一个时间点过期,造成大量的查询透过redis进入到数据库

  • 解决方案:设置不同的过期时间

redis缓存支持

指定缓存的内存空间大小 maxmemory 100mb
达到内存上限时如何删除? maxmemory-policy

  • noeviction:返回错误,当内存限制达到并且客户端尝试执行会让更多内存被使用的命令(大部分的写入指令,但DEL和几个例外)
  • allkeys-lru: 尝试回收最少使用的键(LRU),使得新添加的数据有空间存放。
  • volatile-lru: 尝试回收最少使用的键(LRU),但仅限于带有过期时间的键,使得新添加的数据有空间存放。
  • allkeys-random: 回收随机的键使得新添加的数据有空间存放。
  • volatile-random: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。
  • volatile-ttl: 回收在过期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间存放。

LRU Least-Recently-Used 最近最少使用