先说下题外话,前几天看见一篇关于redis缓存的文章一开始没放在心上,因为我也用过redis来做过购物车。我经常思考redis到底能用来做什么,如果是用于存取数据的话,那又和消息中间件有什么区别呢,存取都能办到,就是单纯的靠速度快吗?
redis是用来存取数据的,优点是依托于内存速度快,采用键值对的形式。RabbitMQ是消息中间件,通过生产者和消费者方式理解。看文章经常能看到淘宝通过redis缓存数据解决亿万数据并发什么的,但我用redis通过RedisTemplate存取数据,还是类似于数据库调用存取操作也并没有感受到很特别的地方。
因为我现在也是在用阿里云建网站,和以前在本地编程还是有区别的更看重速度了,所以我用了这个redis做缓存了只想说厉害。很多思路一下子被打开了。接下来且听我详细讲解一波。
redis做缓存做了什么
实现数据缓存,如果缓存中没有数据,则从数据库查询,并且写入redis缓存。如果redis缓存中有数据,则直接从redis中读取。
通过Linux来理解,如果学过操作系统是知道内存管理的,是要会算内存的命中率的,内存管理就是把一些比较重要,计算机经常会访问的数据存入内存中,这样就可以直接通过内存读取。redis缓存也同理,把一些复杂重要的信息,存起来这样就不用每次连接数据池通过数据库来查询出来,例如说读某一用户的购物车,购物车挺复杂,要先通过用户查查购物车,在通过购物车查商品的详细信息。通过缓存就可以查过一次后,下一次直接获取,速度会快很多。
实现
1.依赖
<!-- redis依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- cache依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- json格式转换-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.46</version>
</dependency>
2.配置
!--RedisProperties!--Redis数据库索引(默认为0)
spring.redis.database=0
!--Redis服务器地址
spring.redis.host=127.0.0.1
!--Redis服务器连接端口
spring.redis.port=6379
!--Redis服务器连接密码(默认为空)
spring.redis.password=
!--连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=8
!--连接池最大阻塞等待时间(使用负值表示没有限制)
!--spring.redis.jedis.pool.max-wait=-1
!--连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=8
!-- # 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
3.Redis缓存配置
@Configuration
//开启缓存
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory){
//创建FastJson对象,用于序列化
GenericFastJsonRedisSerializer fastJsonRedisSerializer = new GenericFastJsonRedisSerializer();
//创建一个RedisCache的配置对象
RedisCacheConfiguration config=RedisCacheConfiguration.defaultCacheConfig();
//过期时间设置为一天
//对存的的key,value进行序列化
config=config.entryTtl(Duration.ofDays(1))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer))
.disableCachingNullValues();
//自己定义要缓存的内存空间名字
Set<String> cacheNames=new HashSet<>();
cacheNames.add("user");
//对缓存空间设置单独的配置,在这个可根据业务,如果数据很久才会变一次时间就可设成永久
Map<String,RedisCacheConfiguration> configMap=new HashMap<>();
configMap.put("user",config);
//创建RedisCacheManage对象,将上面的配置导入
RedisCacheManager redisCacheManager=RedisCacheManager.builder(factory)
.initialCacheNames(cacheNames)
.withInitialCacheConfigurations(configMap)
.build();
return redisCacheManager;
}
}
我上面这个配置是我看了很多篇文章博采众长写出来的,和别人有些不一样。别人的文章是通过Jackson2JsonRedisSerializer来序列化的,我通过fastjson,而且有些他们是直接把redisTemplate的序列化配置好,我觉得可写可不写,关系不大,用fastjson转换代码少也很快。还有一个是 RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate); 对于这个的我只想说大人,时代变了。这是Spring1.0的写法。
借鉴了:
【SpringBoot2.0系列08】SpringBoot之redis数据缓存管理
4.代码测试
1.controller层
@RestController
public class CUser_info {
@Autowired
private User_infoService user_infoService;
@RequestMapping("/api/AllAddressOfUser")
public User_info selAllAddressOfUser(HttpServletRequest request){
return user_infoService.selAllAddressOfUser(1);
}
}
2.service层
@Service
public class User_infoService {
@Autowired
User_infoMapper user_infoMapper;
public User_info selUser_info(int id){
System.out.println(id);
return user_infoMapper.selUser_info(id);
}
public List<User_info> selAll(){
return user_infoMapper.selAll();
}
//root是cache提供的一个对象,里面有什么参数看下面的链接,这里的#root.args[0]指第一个参数也就是user_id
//用了三元运算符是为了,假如这个方法可以拿所有用户的信息和单独user_id用户的信息。
//就可以通过0来区分来0是全搜,有具体的就是相应用户的信息,这样就可以实现按用户来获取redis的缓存信息了
@Cacheable(value = "user",key = "#root.args[0] eq 0 ? 0 : #root.args[0]")
public User_info selAllAddressOfUser(int user_id){
return user_infoMapper.selAllAddressOfUser(user_id);
}
}
使用spring自带的Cacheable注解处理Redis缓存
5.运行
1.第一次运行
执行了sql语句
2.第二次运行
没发生变化就对了,是因为redis里有这个了,所以根本没执行里面的sql操作
以键名value(user)+key(user_id)的方式被存入了redis中。为什么是文件夹呢? 是因为这次插入redis的值是一个有前缀的东西,我觉得是为了便于管理,统一放到user里面。有些人可能会发现自己的redis好像创建不了文件夹,这是正常的,本来就没有建文件夹的按钮。
方法很简单就是加上::这个号就会自动识别了
昨晚花了不少的时间来实现这个redis缓存,看了很多的文章,就比如说我上面的借鉴,按着他们的来也能实现,但不是我想要的,我就是想用fastjson来序列化,就是觉得没必要重写redisTemplate进行序列化配置。我觉得三元运算符用上还是很重要得,就像我上面说的假如一个方法实现了获取全部成员和单独成员得信息,就必须要有一个0这样的数作为标识符来区分。实现一个东西的方法很多但还是要举一反三,融入自己的项目中。不然配置就真的就是配置一下了。