跳到主要内容
版本:4.1.1

驱动

Doubao 中英对照 Drivers

使用 Redis 和 Spring 时的首要任务之一是通过 IoC 容器连接到存储。为此,需要一个 Java 连接器(或绑定库)。无论你选择哪个库,都只需使用同一套 Spring Data Redis API(它在所有连接器之间行为一致),即 org.springframework.data.redis.connection 包及其 RedisConnection 和 RedisConnectionFactory 接口,用于处理和获取到 Redis 的活动连接。

RedisConnection 与 RedisConnectionFactory {#redis:connectors:connection}​

RedisConnection 提供了 Redis 通信的核心构建块,因为它负责与 Redis 后端的通信。它还会自动将底层连接库的异常转换为 Spring 一致的 DAO 异常体系,这样你无需修改任何代码即可切换连接器,因为操作语义保持不变。

备注

对于需要使用原生库 API 的边角情况,RedisConnection 提供了一个专用方法(getNativeConnection),返回用于通信的底层原始对象。

活动的 RedisConnection 对象通过 RedisConnectionFactory 创建。此外,该工厂还充当 PersistenceExceptionTranslator 对象,这意味着一旦声明它们,你就可以进行透明的异常转换。例如,你可以通过使用 @Repository 注解和 AOP 来进行异常转换。更多信息请参见 Spring Framework 文档中专门的章节。

备注

RedisConnection 类不是线程安全的。虽然底层原生连接(例如 Lettuce 的 StatefulRedisConnection)可能是线程安全的,但 Spring Data Redis 的 LettuceConnection 类本身并不是。因此,你不应该在多个线程之间共享 RedisConnection 实例。对于事务性或阻塞性的 Redis 操作和命令(例如 BLPOP)尤其如此。例如,在事务和流水线操作中,RedisConnection 会持有未加保护的可变状态以正确完成操作,从而使其不能在多线程下安全使用。这是有意为之的设计。

提示

如果你需要出于性能原因或其他原因在多个线程之间共享(有状态的)Redis 资源(例如连接),那么你应该获取原生连接并直接使用 Redis 客户端库(驱动)的 API。或者,你可以使用 RedisTemplate,它以线程安全的方式为操作(和 Redis 命令)获取并管理连接。更多细节请参见 RedisTemplate 的文档。

备注

根据底层配置的不同,工厂可以返回一个新连接,或返回一个现有连接(当使用连接池或共享原生连接时)。

使用 RedisConnectionFactory 的最简单方式是通过 IoC 容器配置合适的连接器,并将其注入到使用它的类中。

不幸的是,目前并非所有连接器都支持所有 Redis 功能。当在 Connection API 上调用底层库不支持的方法时,会抛出 UnsupportedOperationException。以下概览说明了各个 Redis 连接器所支持的功能:

表 1. Redis 各连接器的功能支持情况

支持的功能LettuceJedis
独立节点连接XX
主/副本连接X
Redis Sentinel主节点查找、Sentinel 认证、副本读取主节点查找
Redis Cluster集群连接、集群节点连接、副本读取集群连接、集群节点连接
传输通道TCP、操作系统原生 TCP(epoll、kqueue)、Unix 域套接字TCP
连接池X(使用 commons-pool2)X(使用 commons-pool2)
其他连接特性非阻塞命令共享单例连接流水线操作与事务互斥。在流水线/事务中不能使用服务器/连接命令。
SSL 支持XX
发布/订阅XX
流水线操作XX(流水线操作与事务互斥)
事务XX(流水线操作与事务互斥)
数据类型支持Key、String、List、Set、Sorted Set、Hash、Server、Stream、Scripting、Geo、HyperLogLogKey、String、List、Set、Sorted Set、Hash、Server、Stream、Scripting、Geo、HyperLogLog
响应式(非阻塞)APIX

配置 Lettuce 连接器 {#redis:connectors:lettuce}​

Lettuce 是一个基于 Netty- 的开源连接器,Spring Data Redis 通过 org.springframework.data.redis.connection.lettuce 包对其提供支持。

<dependencies>

<!-- other dependency elements omitted -->

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

</dependencies>

下例展示了如何创建一个新的 Lettuce 连接工厂:

@Configuration
class AppConfig {

@Bean
public LettuceConnectionFactory redisConnectionFactory() {

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

还有一些 Lettuce 专用的连接参数可以调整。默认情况下,LettuceConnectionFactory 创建的所有 LettuceConnection 实例对于所有非阻塞、非事务性操作共享同一个线程安全的原生连接。若要每次都使用专用连接,请将 shareNativeConnection 设置为 false。LettuceConnectionFactory 还可以配置为使用 LettucePool 来池化阻塞性和事务性连接,或者在 shareNativeConnection 设为 false 时池化所有连接。

下例展示了一个更复杂的配置,包含 SSL 和超时设置,它使用了 LettuceClientConfigurationBuilder:

@Bean
public LettuceConnectionFactory lettuceConnectionFactory() {

LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
.useSsl().and()
.commandTimeout(Duration.ofSeconds(2))
.shutdownTimeout(Duration.ZERO)
.build();

return new LettuceConnectionFactory(new RedisStandaloneConfiguration("localhost", 6379), clientConfig);
}

更多关于客户端配置的细节调整,请参见 LettuceClientConfiguration。

Lettuce 与 Netty 的原生传输集成,让你可以使用 Unix 域套接字与 Redis 通信。请务必包含与你的运行环境相匹配的原生传输依赖。下例展示了如何为位于 /var/run/redis.sock 的 Unix 域套接字创建 Lettuce 连接工厂:

@Configuration
class AppConfig {

@Bean
public LettuceConnectionFactory redisConnectionFactory() {

return new LettuceConnectionFactory(new RedisSocketConfiguration("/var/run/redis.sock"));
}
}
备注

Netty 目前支持用于操作系统原生传输的 epoll(Linux)和 kqueue(BSD/macOS)接口。

配置 Jedis 连接器 {#redis:connectors:jedis}​

Jedis 由 Spring Data Redis 模块通过 org.springframework.data.redis.connection.jedis 包提供支持。

<dependencies>

<!-- other dependency elements omitted -->

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

</dependencies>

最简单形式的 Jedis 配置如下所示:

@Configuration
class AppConfig {

@Bean
public JedisConnectionFactory redisConnectionFactory() {
return new JedisConnectionFactory();
}
}

但在生产环境中,你可能希望调整诸如主机或密码之类的设置,如下例所示:

@Configuration
class RedisConfiguration {

@Bean
public JedisConnectionFactory redisConnectionFactory() {

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