Docker安装Redis(如果已安装请跳过这一步)
1、拉取Redis镜像(默认最新版本)
docker pull redis
如果下载比较慢的话建议配置阿里云镜像
查看阿里云镜像:阿里云官网-->产品-->搜索容器镜像服务-->管理控制台
左侧边栏下方的镜像加速器:
点进去可以看到下方有一个加速地址和使用方法:
把大括号及大括号里的内容复制进/etc/docker/daemon.json文件中:
vim /etc/docker/daemon.json
重新加载daemon文件和docker即添加镜像成功
systemctl daemon-reload
systemctl restart docker
2、安装完redis镜像后查看是否安装成功
docker images
3、运行redis
docker run -d -p 6379:6379 --name myredis redis
4、查看是否运行成功
docker ps
快速使用Redis
1、导入Redis的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2、添加配置文件
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址(默认为localhost)
spring.redis.host=localhost
# Redis服务器连接端口(默认为6379)
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制) 默认 8
spring.redis.lettuce.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
spring.redis.lettuce.pool.max-wait=-1
# 连接池中的最大空闲连接 默认 8
spring.redis.lettuce.pool.max-idle=8
# 连接池中的最小空闲连接 默认 0
spring.redis.lettuce.pool.min-idle=0
3、添加Redis配置类
自定义一个RedisCacheManager
@Configuration
public class MyRedisConfig {
@Bean
public RedisCacheManager defaultRedisCacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration cacheConfiguration =
RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(6)) // 设置缓存过期时间为6小时
.disableCachingNullValues() // 禁用缓存空值,不缓存null校验
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new
GenericJackson2JsonRedisSerializer())); // 设置CacheManager的值序列化方式为json序列化
return RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(cacheConfiguration).build(); // 设置默认的cache组件
}
}
4、开启基于注解的缓存:@EnableCaching
@EnableCaching
@SpringBootApplication
public class BlogApplication {
public static void main(String[] args) {
SpringApplication.run(BlogApplication.class, args);
}
}
5、使用@Cacheable注解进行缓存
@Cacheable主要针对方法配置,能够根据方法的请求参数对其结果进行缓存
@Service
public class BlogServiceImpl implements BlogService {
@Autowired
private BlogMapper blogMapper;
@Cacheable(cacheNames = "totalBlog")
@Override
public Long getTotalBlogs() {
return blogMapper.getTotalBlogs();
}
}
原理:
- 方法运行之前,先去查询Cache(缓存组件),按照cacheNames指定的名字获取
- 没有查到缓存就调用目标方法,并将目标方法的返回的结果放进缓存中
- 查到了缓存就直接使用缓存,就不会再去数据库查询数据
执行完以上步骤即使用完成。
踩过的坑:反序列化获取数据发生类型转换异常
往Redis中存储Long类型的数据时,反序列化时发生Integer转Long类型转换异常;
我明明存的是Long
类型的数据啊,怎么存进去就变成Integer
类型了呢?
这要从自定义CacheManager
说起......
@Configuration
public class MyRedisConfig {
@Bean
public RedisCacheManager defaultRedisCacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration cacheConfiguration =
RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(6)) // 设置缓存过期时间为6小时
.disableCachingNullValues() // 禁用缓存空值,不缓存null校验
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new
GenericJackson2JsonRedisSerializer())); // 设置CacheManager的值序列化方式为json序列化
return RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(cacheConfiguration).build(); // 设置默认的cache组件
}
}
我们自定义CacheManager
的时候,使用的是GenericJackson2JsonRedisSerializer
序列化器,而GenericJackson2JsonRedisSerializer
在反序列化的时候会统一将缓存反序列化为Object类型,又因为我们存的值是小于Integer.MAX_VALUE
的,自然而然的就转为了Integer。
而我们要解决这种情况的话,只有在存数据的时候就指定数据类型,可以使用Jackson2JsonRedisSerializer
:
@Bean
public RedisCacheManager longRedisCacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration cacheConfiguration =
RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(6)) // 设置缓存过期时间为6小时
.disableCachingNullValues() // 禁用缓存空值,不缓存null校验
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new
Jackson2JsonRedisSerializer<Long>(Long.class))); // 设置CacheManager的值序列化方式为json序列化,指定我们所存的数据为Long类型,取出时自然会帮我们反序列化成Long类型
return RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(cacheConfiguration).build(); // 设置默认的cache组件
}
当存在两个或两个以上的RedisCacheManager
的时候,我们必须在某个RedisCacheManager
上标注@Primary
注解,来表示这个RedisCacheManager
是主要的;当然在使用缓存注解来进行缓存的时候,如果需要使用指定的RedisCacheManager
,就可以使用cacheManager属性进行指定,如果没有指定,就默认使用标注了@Primary
注解的RedisCacheManager
@Cacheable(cacheNames = "totalBlog",cacheManager = "longRedisCacheManager")
@Override
public Long getTotalBlogs() {
return blogMapper.getTotalBlogs();
}