在 Spring 中使用 Redis

添加依赖

1
2
3
4
5
6
7
8
9
10
11
<dependencies>

<!-- other dependency elements omitted -->

<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>3.1.0-SNAPSHOT</version>
</dependency>

</dependencies>

连接 Redis

使用 Redis 和 Spring 的首要任务之一是通过 IoC 容器连接到 store。要做到这一点,需要一个 Java connector(或 binding)。无论你选择哪种库,你都只需要使用一套 Spring Data Redis API,用于处理和检索到 Redis 的活动连接。

RedisConnection 和 RedisConnectionFactory

RedisConnection 提供了 Redis 通信的核心构建模块,因为它处理与 Redis 后端的通信。
活动的 RedisConnection 对象是通过 RedisConnectionFactory 创建的。

连接 redis 库

Lettuc

配置

1
2
3
4
5
6
7
8
9
10
11
<dependencies>

<!-- other dependency elements omitted -->

<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>6.2.2.RELEASE</version>
</dependency>

</dependencies>

实例:

1
2
3
4
5
6
7
8
9
10
@Configuration
class AppConfig {

@Bean
public LettuceConnectionFactory redisConnectionFactory() {

return new LettuceConnectionFactory(new RedisStandaloneConfiguration("server", 6379));
}
}

Jedis

配置

1
2
3
4
5
6
7
8
9
10
11
12
<dependencies>

<!-- other dependency elements omitted -->

<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.3.1</version>
</dependency>

</dependencies>

实例:

1
2
3
4
5
6
7
8
9
10
11
12
@Configuration
class RedisConfiguration {

@Bean
public JedisConnectionFactory redisConnectionFactory() {

RedisStandaloneConfiguration config = new RedisStandaloneConfiguration("server", 6379);
return new JedisConnectionFactory(config);
}
}


读写分离(写主节点,读从节点)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Configuration
class WriteToMasterReadFromReplicaConfiguration {

@Bean
public LettuceConnectionFactory redisConnectionFactory() {

LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
.readFrom(REPLICA_PREFERRED)
.build();

RedisStandaloneConfiguration serverConfig = new RedisStandaloneConfiguration("server", 6379);

return new LettuceConnectionFactory(serverConfig, clientConfig);
}
}

Redis Sentinel(哨兵)

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
/**
* Lettuce
*/
@Bean
public RedisConnectionFactory lettuceConnectionFactory() {
RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration()
.master("mymaster")
.sentinel("127.0.0.1", 26379)
.sentinel("127.0.0.1", 26380);
return new LettuceConnectionFactory(sentinelConfig);
}

/**
* Jedis
*/
@Bean
public RedisConnectionFactory jedisConnectionFactory() {
RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration()
.master("mymaster")
.sentinel("127.0.0.1", 26379)
.sentinel("127.0.0.1", 26380);
return new JedisConnectionFactory(sentinelConfig);
}


RedisTemplate 处理对象

引入 RedisTemplate 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Configuration
class MyConfig {

@Bean
LettuceConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}

@Bean
RedisTemplate<String, String> redisTemplate(RedisConnectionFactory redisConnectionFactory) {

RedisTemplate<String, String> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}


使用 Redis 对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Example {

// inject the actual template
@Autowired
private RedisTemplate<String, String> template;

// inject the template as ListOperations
@Resource(name="redisTemplate")
private ListOperations<String, String> listOps;

public void addLink(String userId, URL url) {
listOps.leftPush(userId, url.toExternalForm());
}
}


以字符串为中心的便利类

由于存储在 Redis 中的 key 和 value 是很常见的 java.lang.String,Redis 模块提供了两个 RedisConnection 和 RedisTemplate 的扩展,分别是 StringRedisConnection(及其 DefaultStringRedisConnection 实现)和 StringRedisTemplate,作为密集字符串操作的方便的一站式解决方案。

引入类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Configuration
class MyConfig {

@Bean
LettuceConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}

@Bean
StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {

StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}

使用

1
2
3
4
5
6
7
8
9
10
11
public class Example {

@Autowired
private StringRedisTemplate redisTemplate;

public void addLink(String userId, URL url) {
redisTemplate.opsForList().leftPush(userId, url.toExternalForm());
}
}


1
2
3
4
5
6
7
8
9
10
11
12
public void useCallback() {

redisTemplate.execute(new RedisCallback<Object>() {
public Object doInRedis(RedisConnection connection) throws DataAccessException {
Long size = connection.dbSize();
// Can cast to StringRedisConnection if using a StringRedisTemplate
((StringRedisConnection)connection).set("key", "value");
}
});
}


事务

1
2
3
4
5
6
7
8
9
10
11
12
//execute a transaction
List<Object> txResults = redisTemplate.execute(new SessionCallback<List<Object>>() {
public List<Object> execute(RedisOperations operations) throws DataAccessException {
operations.multi();
operations.opsForSet().add("key", "value1");

// This will contain the results of all operations in the transaction
return operations.exec();
}
});
System.out.println("Number of items added to set: " + txResults.get(0));

默认情况下,RedisTemplate 不参与管理 Spring 事务。如果你想让 RedisTemplate 在使用 @Transactional 或 TransactionTemplate 时利用 Redis 事务,你需要通过设置 setEnableTransactionSupport(true) 为每个 RedisTemplate 明确启用事务支持,事务支持将 RedisConnection 绑定到由 ThreadLocal 支持的当前事务。

管道

1
2
3
4
5
6
7
8
9
10
11
12
13
//pop a specified number of items from a queue
List<Object> results = stringRedisTemplate.executePipelined(
new RedisCallback<Object>() {
public Object doInRedis(RedisConnection connection) throws DataAccessException {
StringRedisConnection stringRedisConn = (StringRedisConnection)connection;
for(int i=0; i< batchSize; i++) {
stringRedisConn.rPop("myqueue");
}
return null;
}
});


缓存

使用 redis 作为缓存实现,需要添加配置类

1
2
3
4
5
6
7
8
9
10
11
12
RedisCacheManager cm = RedisCacheManager.builder(connectionFactory)
.cacheDefaults(defaultCacheConfig())
.withInitialCacheConfigurations(singletonMap("predefined", defaultCacheConfig().disableCachingNullValues()))
.transactionAware()
.build();

// 加入锁行为
RedisCacheManager cm = RedisCacheManager.build(RedisCacheWriter.lockingRedisCacheWriter(connectionFactory))
.cacheDefaults(defaultCacheConfig())
...