缓存(入门)

本文介绍了缓存的基本概念、优化顺序以及常见问题。重点讲述了Redis作为缓存的使用,包括memcached与redis的对比、Redis缓存策略、SpringBoot中使用Redis缓存的配置和注解使用,以及Jedis和Lettuce客户端的区别。同时讨论了Redis配置类和编程使用,如RedisTemplate的操作。
摘要由CSDN通过智能技术生成

缓存

为了减少数据库的访问次数,以浪费内存为代价,提高查询效率,所以引入缓存

  • 优化顺序: 内存>网络>磁盘
  • 问题:双写问题

缓存常见的实现方案

  • memcached
  • redis 11万读/8万写

Redis缓存

  • 使用场景

    • 降低后端负载
    • 加速请求响应
    • 大量写合并为批量写
  • Redis缓存策略

    • LRU、LFU、FIFO
    • 超时剔除
    • 主动更新
  • 缓存粒度控制

    • 通用性:全量属性更好
    • 占用空间:部分属性更好
    • 代码维护:表面上全量属性最好
  • 缓存穿透问题

    • 现象:请求访问redis,redis没有缓存,然后再访问mysql,但是mysql中也没有,下次在请求的时候,redis中也没有,这样就是缓存穿透的问题
    • 解决方法
      • 缓存空对象
      • 布隆过滤器拦截
  • 无底洞问题:更多的集器不代表更好的性能

    • 命令行的优化,减少慢查询,比如:keys *,hgetall bigkey
    • 减少网络通信次数
    • 降低接入成本
  • 热点key的重建

    • 减少重缓存的次数

    • 数据尽可能一致

    • 减少潜在危险

    • 解决方案

      • 互斥锁:获取缓存的时候加锁,重建缓存完成之后再解锁
      • 永不过期:逻辑上设置键是永不过期的

springboot使用redis缓存

spring针对持久化操作引入了spring data

  • 针对RDBMS引入了spring data jpa
  • 针对不同的NoSQL数据库提供了对应的实现
    • spring-data-redis采用的是RedisTemplate方式

引入依赖

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--如果需要使用连接池 -->
<dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
</dependency>

全局配置

spring:
  cache:
    type: redis   # 声明所使用的缓存类型

# 针对redis链接的配置
  redis:
    host: localhost
    port: 6379
# 针对lettuce配置,如果没有优化配置参数则使用默认值
    lettuce:
      pool:
        max-active: 8
        max-wait: 10000ms
        max-idle: 2

在主类上添加注解启用缓存

@EnableCaching
public class Springboot11Application 

@EnableCaching注解是spring framework中的注解驱动的缓存管理功能。自spring版本3.1起加入了该注解。

  • 如果你使用了这个注解,那么你就不需要在XML文件中配置cache manager了
  • 当你在配置类(@Configuration)上使用@EnableCaching注解时,会触发一个post processor,这会扫描每一个spring bean,查看是否已经存在注解对应的缓存。如果找到了,就会自动创建一个代理拦截方法调用,使用缓存的bean执行处理。

@Cacheable:作用是主要针对方法配置,能够根据方法的请求参数对其结果进行缓存

  • value :缓存的名称,在 spring 配置文件中定义,必须指定至少一个,
    例如:@Cacheable(value=”mycache”) 或者 @Cacheable(value={”cache1”,”cache2”}。
  • key :缓存的 key,可以为空,
    如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合,
    例如:@Cacheable(value=”testcache”,key=”#userName”)。
  • condition:指定符合条件的情况下才缓存;如condition="#id>0"
  • unless:否定缓存,当unless指定的条件为true,方法的返回值不会被缓存,可以获取到结果进行判断;如unless="#result==null";
@RestController  //复合注解
@RequestMapping("/users")
public class UserController {
    @Autowired
    private IUserServ userService;
    @GetMapping("/{id}")
    @Cacheable(value="users",key = "#p0",unless = "#result==null")
    public User load(@PathVariable("id") Long id){
        return userService.getById(id);
    }
}

@CachePut作用是主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实查询

参数配置和@Cacheable一样

@RestController  //复合注解
@RequestMapping("/users")
public class UserController {
    @Autowired
    private IUserServ userService;
    @CachePut(value="users",key = "#result.id",condition = "#result!=null")
    @PostMapping
    public User create(User user) {
        boolean bb = userService.create(user);
        if (bb)
            return user;
        return null;
    }
}

@CacheEvict:作用是主要针对方法配置,能够根据一定的条件对缓存进行清空

  • value , key 和 condition 参数配置和@Cacheable一样
  • allEntries :是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存
  • beforeInvocation是否在方法执行前就清空,缺省为 false。如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存,
@DeleteMapping("/{id}")
@CacheEvict(value = "users",allEntries = true)
public void remove(@PathVariable Long id){
     userService.remove(id);
}

@Caching注解将其他注解方式融合在一起了,可以根据需求来自定义注解,并将前面三个注解应用在一起。@Caching注解可以在一个方法或者类上同时指定多个Spring Cache相关的注解。其拥有三个属性:cacheable、put和evict,分别用于指定@Cacheable、@CachePut和@CacheEvict。

@Caching(
    put = {
   	   @CachePut(value = "users", key = "#result.id", condition = "#result!=null")
    }, evict = {
       @CacheEvict(value = "users", key = "'all'")
    }
)
    @PostMapping
    public User create(User user) {
        boolean bb = userService.create(user);
        if (bb)
            return user;
        return null;
    }

@CacheConfig(cacheNames=“users”)用于标注在类上,可以存放该类中所有缓存的公有属性,比如设置缓存的名字

redis的客户端

Redis的Java客户端很多,官方推荐的有三种:Jedis、Redisson和lettuce。

Jedis/jie’dai/:

  • 轻量,简洁,便于集成和改造,线程不安全的
  • 支持连接池
  • 支持pipelining、事务、LUA Scripting、Redis Sentinel、Redis Cluster
  • 不支持读写分离,需要自己实现
  • 文档差(真的很差,几乎没有……)

lettuce/lai’tei’si/是一个线程安全的redis客户端。提供同步,异步和reactive的APIs.。如果可以避开阻塞和事务型的操作比如BLPOPMULTI/EXEC,多个线程可以分享同一个连接。多个连接被NIO框架netty有效的管理。SpringBoot推荐使用

jedis和lettuce的区别

Jedis 和 Lettuce 是 Java 操作 Redis 的客户端。在 Spring Boot 1.x 版本默认使用的是 jedis ,而在 Spring Boot 2.x 版本默认使用的就是Lettuce。关于 Jedis 跟 Lettuce 的区别如下:

  • Jedis在实现上是直接连接的redis server,如果在多线程环境下是非线程安全的,这个时候只有使用连接池,为每个Jedis实例增加物理连接
  • Lettuce的连接是基于Netty的,连接实例(StatefulRedisConnection)可以在多个线程间并发访问,应为StatefulRedisConnection是线程安全的,所以一个连接实例(StatefulRedisConnection)就可以满足多线程环境下的并发访问,当然这个也是可伸缩的设计,一个连接实例不够的情况也可以按需增加连接实例。

redis配置类

在默认的情况下,两者整合后便可将数据缓存到redis,但是缓存进去的对象类型数据是经过jdk默认序列化过后的,在可视化工具中是HEX格式,看起来非常不方便,所以需要进行格式化

@EnableCaching
@Configuration
public class RedisConfig {
    @Bean
    public CacheManager cacheManager(LettuceConnectionFactory factory) {
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jsonRedisSerializer))
                .disableCachingNullValues();
        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
        cacheManager.afterPropertiesSet();
        return cacheManager;
    }
}

Redis编程使用

与使用注解方式不同,注解方式可以零配置,只需引入依赖并在启动类上加上@EnableCaching 注解就可以使用;而使用 RedisTemplate 方式麻烦些,需要做一些配置。

 @Bean
    @ConditionalOnMissingBean(StringRedisTemplate.class)
    public StringRedisTemplate stringRedisTemplate(
            RedisConnectionFactory redisConnectionFactory)
            throws UnknownHostException {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

RedisTemplate 对五种数据结构分别定义了操作

  • redisTemplate.opsForValue();操作字符串
  • redisTemplate.opsForHash();操作hash
  • redisTemplate.opsForList();操作list
  • redisTemplate.opsForSet();操作set
  • redisTemplate.opsForZSet();操作有序set
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值