Hello,各位小伙伴,最近项目中需要将一些常用的数据缓存起来,毫无疑问,我们采用了Redis来缓存数据。那么使用
Redis缓存数据有哪些方式
呢?接下来我会一一道来。
引入Redis依赖以及Spring相关的依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
使用RedisTemplate调用API时,我们通常需要去配置key,value的序列化器,以及创建一个RedisUtils类来完成缓存的增删改查以及过期时间的设置。
配置如下:
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 设置key的序列化方式
template.setKeySerializer(RedisSerializer.string());
// 设置value的序列化方式
template.setValueSerializer(RedisSerializer.json());
// 设置hash的key的序列化方式
template.setHashKeySerializer(RedisSerializer.string());
// 设置hash的value的序列化方式
template.setHashValueSerializer(RedisSerializer.json());
template.afterPropertiesSet();
return template;
}
}
RedisUtils:
public class RedisUtils {
@Resource
private RedisTemplate<String, Object> redisTemplate;
public Object get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}
/**
* 普通缓存放入
*
* @param key 键
* @param value 值
*/
public void set(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
/**
* 普通缓存放入并设置时间
*
* @param key 键
* @param value 值
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
*/
public void set(String key, Object value, long time) {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
set(key, value);
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
*/
public void hset(String key, String item, Object value) {
redisTemplate.opsForHash().put(key, item, value);
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
* @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
*/
public void hset(String key, String item, Object value, long time, TimeUnit timeUnit) {
redisTemplate.opsForHash().put(key, item, value);
if (time > 0) {
expire(key, time, timeUnit);
}
}
/**
* @param key 键
* @param map 多个field-value
*/
public void hmset(String key, Map<String, Object> map) {
redisTemplate.opsForHash().putAll(key, map);
}
/**
* @param key 键
* @param map 多个field-value
* @param time 过期时间
* @param timeUnit 时间单位
*/
public void hmset(String key, Map<String, Object> map, long time, TimeUnit timeUnit) {
redisTemplate.opsForHash().putAll(key, map);
if (time > 0) {
expire(key, time, timeUnit);
}
}
/**
* @param key 键
* @param item Field
* @return 获得的值
*/
public Object hget(String key, String item) {
return redisTemplate.opsForHash().get(key, item);
}
/**
* @param key 键
* @return hash表中key对应的map
*/
public Map<Object, Object> hEntries(String key) {
return redisTemplate.opsForHash().entries(key);
}
/**
* @param key 键
* @param value 值
*/
public void sadd(String key, Object value) {
redisTemplate.opsForSet().add(key, value);
}
/**
* @param key 键
* @param value 值
* @param time 过期时间
* @param timeUnit 时间单位
*/
public void sadd(String key, Object value, long time, TimeUnit timeUnit) {
redisTemplate.opsForSet().add(key, value);
if (time > 0) {
expire(key, time, timeUnit);
}
}
/**
* @param key 键
* @return 数据
*/
public Set<Object> smembers(String key) {
return redisTemplate.opsForSet().members(key);
}
public void expire(String key, long time, TimeUnit timeUnit) {
if (time > 0) {
redisTemplate.expire(key, time, timeUnit);
}
}
/**
* 根据key 获取过期时间
*
* @param key 键 不能为null
* @return 时间(秒) 返回0代表为永久有效
*/
public long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
}
通过以上的配置,我们在使用缓存的时候,直接调用API就可以进行操作了。但是有个问题就是,我们在缓存一些常用数据的时候,通常我们需要先判断一下缓存中有没有该key,如果没有我们再去数据库中查询出来,并缓存。这样的话我们需要去做一些判断的操作,缓存中有就去缓存中取,没有就从数据库中取出来并缓存。那么有没有更方便的操作方式呢,答案当然是有的。❤️
Spring为我们提供了Caching模块,我们可以该模块给我们提供的功能,使用注解很方便完成数据缓存
在使用的过程中,我发现,虽然我们配置了RedisTemplate的序列化,但是对于基于注解的Redis缓存来说是无效的
,我们需要配置自定义的RedisCacheManager
配置如下:
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 设置key的序列化方式
template.setKeySerializer(RedisSerializer.string());
// 设置value的序列化方式
template.setValueSerializer(RedisSerializer.json());
// 设置hash的key的序列化方式
template.setHashKeySerializer(RedisSerializer.string());
// 设置hash的value的序列化方式
template.setHashValueSerializer(RedisSerializer.json());
template.afterPropertiesSet();
return template;
}
@Bean
public RedisCacheManager redisCacheManager(RedisConnectionFactory factory) {
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(factory);
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.string()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.json()));
return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
}
}
使用方法:
- 在启动类上加上
@EnableCaching
- 在需要缓存数据的方法上加上
@Cacheable(cacheNames = "xxx")
,方法的返回值就是我们需要缓存的数据- 基于以上的操作,我们就可以很方便的将需要缓存的数据缓存到Redis