学习笔记@某Spring学习视频

  • 第八天1/2
  • Spring中使用Redis
  • Redis介绍
  • 使用Jedis客户端
  • Redis哨兵模式
  • Spring缓存抽象
  • Spring-Redis缓存抽象


第八天1/2

Spring中使用Redis

redis与spring的整合一般分为spring-data-redis整合和jedis整合
spring-data-redis与spring的整合,更像mybatis与spring整合,通过工厂,创建实例,再操作实例。而jedis,更像spring与MySQL结合,通过操作连接池,获取实例操作数据库

Redis介绍

Redis是开源的内存KV存储
与MongoDB类似,Spring对Redis的支持是通过Spring Data Redis
存在RedisTemplate
redis通常作为非持久化的缓存使用的,而不是像MongoDB那样的持久化的数据存储

使用Jedis客户端

Jedis不是线程安全的,通过JedisPool来管理Jedis实例
具体
JedisPoolConfig配置所有的redis配置

//可以快速将properties中所有的配置注入到JedisPoolConfig中
@ConfigurationProperties(profix="redis")

再注入JedisPool的bean

//value注解绑定redis.host配置
public JedisPool jedisPool(@Value("${redis.host}") String host){
       ···
}

在run中就可以使用

//try with resource写法
        try (Jedis jedis = jedisPool.getResource()) {
             jedis.hset(String key ,String field ,String value);
             jedis.hget(String key ,String field);
             jedis.hgetAll(String key);
        }

代码

package geektime.spring.springbucks;

import...

@Slf4j
@SpringBootApplication
@EnableJpaRepositories
@EnableTransactionManagement
public class jedisApplication implements ApplicationRunner {

    @Autowired
    private CoffeeService coffeeService;

    @Autowired
    private JedisPool jedisPool;
    @Autowired
    private JedisPoolConfig jedisPoolConfig;

    public static void main(String[] args) {
        SpringApplication.run(jedisApplication.class, args);
    }

    @Bean
    @ConfigurationProperties("redis")
    public JedisPoolConfig jedisPoolConfig(){
        return new JedisPoolConfig();
    }

    @Bean(destroyMethod = "close")
    public JedisPool jedisPool(@Value("${redis.host}") String host){
        return new JedisPool(jedisPoolConfig(),host);
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        log.info(jedisPoolConfig.toString());
        try (Jedis jedis = jedisPool.getResource()) {
            coffeeService.findAllCoffee().forEach(c -> {
                jedis.hset("springbucks-menu", c.getName(), Long.toString(c.getPrice().getAmountMinorLong()));
            });

            Map<String, String> menu = jedis.hgetAll("springbucks-menu");
            log.info("Menu: {}", menu);

            String price = jedis.hget("springbucks-menu", "espresso");
            log.info("espresso - {}",
                    Money.ofMinor(CurrencyUnit.of("CNY"), Long.parseLong(price)));
        }
    }
}

Redis哨兵模式

是一种高可用方案

Spring缓存抽象

缓存抽象介绍两种(可能存在更多但视频未介绍)
Spring缓存抽象和Redis缓存抽象

需要在service层中的coffeeService中的方法findAllCoffee添加注解@Cacheable对此方法开启缓存

同时需要在coffeeService类上添加注解@CacheConfig(cacheNames = “coffee”)配置缓存的名字

之后新增方法reloadCoffee

@CacheEvict//此注解就是重新加载缓存的作用
    public void reloadCoffee() {
    }

在Application类中@EnableCaching(proxyTargetClass = true)
之后每次调用findAllCoffee(在缓存过期前)都会命中缓存,从而不读取数据库提高速度及效率

package geektime.spring.springbucks;

import ...

@Slf4j
@EnableTransactionManagement
@SpringBootApplication
@EnableJpaRepositories
@EnableCaching(proxyTargetClass = true)
public class SpringBucksApplication implements ApplicationRunner {
	@Autowired
	private CoffeeService coffeeService;

	public static void main(String[] args) {
		SpringApplication.run(SpringBucksApplication.class, args);
	}

	@Override
   public void run(ApplicationArguments args) throws Exception {
        log.info("Count: {}", coffeeService.findAllCoffee().size());
        for (int i = 0; i < 10; i++) {
            log.info("Reading from cache.");
            coffeeService.findAllCoffee();
        }
        coffeeService.reloadCoffee();
        log.info("Reading after refresh.");
        coffeeService.findAllCoffee().forEach(c -> log.info("Coffee {}", c.getName()));

    }
@Slf4j
@Service
@CacheConfig(cacheNames = "coffee")
public class CoffeeService {
    @Autowired
    private CoffeeRepository coffeeRepository;

    @Cacheable
    public List<Coffee> findAllCoffee() {
        return coffeeRepository.findAll();
    }

    @CacheEvict
    public void reloadCoffee() {
    }
    ···//omit

Spring-Redis缓存抽象

与上述原理大致相同
需要额外添加依赖

<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>

增加redis配置

spring.jpa.hibernate.ddl-auto=none
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true

//下面是增加的配置
management.endpoints.web.exposure.include=*

spring.cache.type=redis
spring.cache.cache-names=coffee
spring.cache.redis.time-to-live=5000
spring.cache.redis.cache-null-values=false

spring.redis.host=localhost

本人理解是相当于把Spring原生的cache用redis-cache替换
额外设置了redis的缓存时间等

缓存时间一过,缓存失效,就会自动重新加载----自动失效自动重载而不需要调用reloadCoffee方法

package geektime.spring.springbucks;

import ...

@Slf4j
@EnableTransactionManagement
@SpringBootApplication
@EnableJpaRepositories
@EnableCaching(proxyTargetClass = true)
public class SpringBucksApplication implements ApplicationRunner {
	@Autowired
	private CoffeeService coffeeService;

	public static void main(String[] args) {
		SpringApplication.run(SpringBucksApplication.class, args);
	}

	@Override
	public void run(ApplicationArguments args) throws Exception {
		log.info("Count: {}", coffeeService.findAllCoffee().size());
		for (int i = 0; i < 5; i++) {
			log.info("Reading from cache.");
			coffeeService.findAllCoffee();
		}
		Thread.sleep(5_000);
		log.info("Reading after refresh.");
		coffeeService.findAllCoffee().forEach(c -> log.info("Coffee {}", c.getName()));
	}
}

以上就是缓存抽象内容