驱动程序
在使用 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 连接器的功能可用性
支持的功能 | Lettuce | Jedis |
---|---|---|
独立连接 | X | X |
主/从连接 | X | |
Redis Sentinel | 主节点查找,Sentinel 认证,从节点读取 | 主节点查找 |
Redis 集群 | 集群连接,集群节点连接,从节点读取 | 集群连接,集群节点连接 |
传输通道 | TCP,操作系统原生 TCP(epoll、kqueue),Unix 域套接字 | TCP |
连接池 | X(使用 commons-pool2 ) | X(使用 commons-pool2 ) |
其他连接功能 | 非阻塞命令的单例连接共享 | 管道和事务互斥。不能在管道/事务中使用服务器/连接命令。 |
SSL 支持 | X | X |
发布/订阅 | X | X |
管道 | X | X(管道和事务互斥) |
事务 | X | X(管道和事务互斥) |
数据类型支持 | 键、字符串、列表、集合、有序集合、哈希、服务器、流、脚本、地理、HyperLogLog | 键、字符串、列表、集合、有序集合、哈希、服务器、流、脚本、地理、HyperLogLog |
响应式(非阻塞)API | X |
配置 Lettuce 连接器 {#redis:connectors:lettuce}
<dependencies>
<!-- other dependency elements omitted -->
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>6.4.1.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 是一个由社区驱动的连接器,通过 org.springframework.data.redis.connection.jedis
包得到 Spring Data Redis 模块的支持。
<dependencies>
<!-- other dependency elements omitted -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>5.2.0</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);
}
}