什么是redis

一个非关系型数据库,可以将一部分数据持久化在本地,但是其内存运行的特性保证了redis的速度,所以多用作web服务的缓存,用于缓解后台服务器数据库的并发压力。

我们是否真的需要redis

redis主要用于缓存数据,在高速读写的环境下使用。

一般来说,我们只有在某些特定的场景中才会需要缓存来加速我们的应用

  • 数据是常用数据吗,业务运行时数据的命中率如何,如果命中率很低,也就是说数据更新频繁,那么就不太适合写入缓存
  • 该业务数据是读取的操作多,还是写入的操作多?写入更多参考上一条,不适合写入缓存
  • 数据量有多少,虽然redis的最大单值容量可以达到512MB但还是不太适合存放过大的数据,而且也没有必要

解决String与JAVA对象的相互转换

redis只支持了六种数据类型,string/hash/list/set/zset/hyperloglog,而没有JAVA中最常使用的object,所以我们需要在string与object做序列化的工作,来调用。

对此我们需要重写redisTemplate的序列化方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.io.Serializable;

@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisCacheConfig {
@Bean
public RedisTemplate<String, Serializable> redisCacheTemplate(LettuceConnectionFactory connectionFactory) {
RedisTemplate<String, Serializable> template = new RedisTemplate<>();
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
template.setConnectionFactory(connectionFactory);
return template;
}
}

在POJO增删改查时中使用缓存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
@Service
public class UserServiceImpl implements UserService {
private static Map<Integer, User> userMap = new HashMap<>();

static {
userMap.put(1, new User(1, "张三", 25));
userMap.put(2, new User(2, "李四", 26));
userMap.put(3, new User(3, "王五", 24));
}

/**
* save操作将会更新缓存
*
* @param user 对象值
* @return
*/
@CachePut(value = "user", key = "#user.id")
@Override
public User save(User user) {
userMap.put(user.getId(), user);
return user;
}

@CacheEvict(value = "user", key = "#id")
@Override
public void delete(int id) {
userMap.remove(id);
return;
}

@Cacheable(value = "user", key = "#id")
@Override
public User get(int id) {
return userMap.get(id);
}

@CachePut(value = "user", key = "#user.id")
@Override
public void update(User user) {
userMap.put(user.getId(), user);
return;
}
}

很明显,对不同的操作,用了不同的缓存策略。

  • 当需要变更数据库的数据时,缓存就会被标记为无效,同时将会更新缓存中的值
  • 当不需要更改,这直接读取缓存而不是去查数据库,这样就能规避数据库查询带来的时间损耗

遇到的错误

1
Could not connect to Redis at 127.0.0.1:6379: Connection refused

连接失败,多是因为redis没有默认在后台运行,可以编辑redis.conf文件中的daemonize属性,来让redis在后台静默运行。

spring boot运行redis项目无法启动

1
Error creating bean with name 'enableRedisKeyspaceNotificationsInitializer'

redis没有启动,启动redis即可解决。