Drivers

在使用 Redis 和 Spring 时首要任务之一是通过 IoC 容器连接到存储。为此,需要一个 Java 连接器(或绑定)。无论你选择哪个库,你都需要只使用一组 Spring Data Redis API(它们在所有连接器中表现一致)。包 org.springframework.data.redis.connection 及其接口 RedisConnectionRedisConnectionFactory 用于处理与 Redis 的活动连接以及检索这些连接。

One of the first tasks when using Redis and Spring is to connect to the store through the IoC container. To do that, a Java connector (or binding) is required. No matter the library you choose, you need to use only one set of Spring Data Redis APIs (which behaves consistently across all connectors). The org.springframework.data.redis.connection package and its RedisConnection and RedisConnectionFactory interfaces for working with and retrieving active connections to Redis.

RedisConnection and RedisConnectionFactory

RedisConnection 提供了 Redis 通信的核心部件,因为它处理与 Redis 后端的通信。它还将底层的连接库异常自动翻译为 Spring 的一致 {spring-framework-docs}/data-access.html#dao-exceptions[DAO 异常体系],这样你就可以在不进行任何代码更改的情况下切换连接器,因为操作语义保持不变。

RedisConnection provides the core building block for Redis communication, as it handles the communication with the Redis backend. It also automatically translates underlying connecting library exceptions to Spring’s consistent {spring-framework-docs}/data-access.html#dao-exceptions[DAO exception hierarchy] so that you can switch connectors without any code changes, as the operation semantics remain the same.

对于需要本机库 API 的特殊情况,RedisConnection 提供有专门方法 (getNativeConnection),用于返回用于通信的原始底层对象。

For the corner cases where the native library API is required, RedisConnection provides a dedicated method (getNativeConnection) that returns the raw, underlying object used for communication.

通过 RedisConnectionFactory 创建活动 RedisConnection 对象。此外,工厂充当 PersistenceExceptionTranslator 对象,这意味着声明后,它们让你进行透明异常翻译。例如,你可以通过使用 @Repository 注解和 AOP 来执行异常转换。有关更多信息,请参阅 Spring Framework 文档中专门的 {spring-framework-docs}/data-access.html#orm-exception-translation[部分]。

Active RedisConnection objects are created through RedisConnectionFactory. In addition, the factory acts as PersistenceExceptionTranslator objects, meaning that, once declared, they let you do transparent exception translation. For example, you can do exception translation through the use of the @Repository annotation and AOP. For more information, see the dedicated {spring-framework-docs}/data-access.html#orm-exception-translation[section] in the Spring Framework documentation.

RedisConnection 类是 not 线程安全的。虽然基础本机连接(例如 Lettuce 的 StatefulRedisConnection)可能是线程安全的,但 Spring Data Redis 的 LettuceConnection 类本身却不是。因此,您应该 not 在多个线程中共享 RedisConnection 的实例。对于事务或阻塞 Redis 操作和命令(例如 BLPOP)而言尤其如此。例如,在事务和管道操作中,RedisConnection 拥有不受保护的可变状态以正确完成操作,因此不适合与多个线程一起使用。这是设计需要。

RedisConnection classes are not Thread-safe. While the underlying native connection, such as Lettuce’s StatefulRedisConnection, may be Thread-safe, Spring Data Redis’s LettuceConnection class itself is not. Therefore, you should not share instances of a RedisConnection across multiple Threads. This is especially true for transactional, or blocking Redis operations and commands, such as BLPOP. In transactional and pipelining operations, for instance, RedisConnection holds onto unguarded mutable state to complete the operation correctly, thereby making it unsafe to use with multiple Threads. This is by design.

如果您需要出于性能原因或其他原因跨多个线程共享(有状态)Redis 资源(例如连接),那么您应获取本机连接并直接使用 Redis 客户端库(驱动程序)API。或者,您可以使用“ RedisTemplate”,它以线程安全的方式获取并管理操作(和 Redis 命令)的连接。有关详细信息,请参阅“ RedisTemplate”上的“ documentation”。

If you need to share (stateful) Redis resources, like connections, across multiple Threads, for performance reasons or otherwise, then you should acquire the native connection and use the Redis client library (driver) API directly. Alternatively, you can use the RedisTemplate, which acquires and manages connections for operations (and Redis commands) in a Thread-safe manner. See documentation on RedisTemplate for more details.

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

Depending on the underlying configuration, the factory can return a new connection or an existing connection (when a pool or shared native connection is used).

处理 RedisConnectionFactory 的最简单方法是通过 IoC 容器配置适当的连接器,并将其注入到使用该连接器的类中。

The easiest way to work with a RedisConnectionFactory is to configure the appropriate connector through the IoC container and inject it into the using class.

很遗憾,目前并不是所有连接器都支持所有的 Redis 功能。当调用底层库不支持的 Connection API 上的方法时,会引发 UnsupportedOperationException。以下概述解释了各个 Redis 连接器支持的功能:

Unfortunately, currently, not all connectors support all Redis features. When invoking a method on the Connection API that is unsupported by the underlying library, an UnsupportedOperationException is thrown. The following overview explains features that are supported by the individual Redis connectors:

Table 1. Feature Availability across Redis Connectors
Supported Feature Lettuce Jedis

Standalone Connections

X

X

Master/Replica Connections

X

Redis Sentinel

Master Lookup, Sentinel Authentication, Replica Reads

Master Lookup

Redis Cluster

Cluster Connections, Cluster Node Connections, Replica Reads

Cluster Connections, Cluster Node Connections

Transport Channels

TCP, OS-native TCP (epoll, kqueue), Unix Domain Sockets

TCP

Connection Pooling

X (using commons-pool2)

X (using commons-pool2)

Other Connection Features

Singleton-connection sharing for non-blocking commands

Pipelining and Transactions mutually exclusive. Cannot use server/connection commands in pipeline/transactions.

SSL Support

X

X

Pub/Sub

X

X

Pipelining

X

X (Pipelining and Transactions mutually exclusive)

Transactions

X

X (Pipelining and Transactions mutually exclusive)

Datatype support

Key, String, List, Set, Sorted Set, Hash, Server, Stream, Scripting, Geo, HyperLogLog

Key, String, List, Set, Sorted Set, Hash, Server, Stream, Scripting, Geo, HyperLogLog

Reactive (non-blocking) API

X

Configuring the Lettuce Connector

Lettuce 是 Spring Data Redis 通过 org.springframework.data.redis.connection.lettuce 包支持的基于 Netty 的开源连接器。

Lettuce is a Netty-based open-source connector supported by Spring Data Redis through the org.springframework.data.redis.connection.lettuce package.

Add the following to the pom.xml files dependencies element:
<dependencies>

  <!-- other dependency elements omitted -->

  <dependency>
    <groupId>io.lettuce</groupId>
    <artifactId>lettuce-core</artifactId>
    <version>{lettuce}</version>
  </dependency>

</dependencies>

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

The following example shows how to create a new Lettuce connection factory:

@Configuration
class AppConfig {

  @Bean
  public LettuceConnectionFactory redisConnectionFactory() {

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

还有几个 Lettuce 特定的连接参数可以微调。默认情况下,由 LettuceConnectionFactory 创建的所有 LettuceConnection 实例对于所有非阻塞和非事务操作共享同一个线程安全的本机连接。为了每次使用一个专用连接,将 shareNativeConnection 设置为 false。也可以将 LettuceConnectionFactory 配置为对阻塞和事务连接使用 LettucePool,或者在 shareNativeConnection 设置为 false 的情况下对所有连接使用。

There are also a few Lettuce-specific connection parameters that can be tweaked. By default, all LettuceConnection instances created by the LettuceConnectionFactory share the same thread-safe native connection for all non-blocking and non-transactional operations. To use a dedicated connection each time, set shareNativeConnection to false. LettuceConnectionFactory can also be configured to use a LettucePool for pooling blocking and transactional connections or all connections if shareNativeConnection is set to false.

下面的示例展示了一个更复杂的配置,包括 SSL 和超时,其中使用了 LettuceClientConfigurationBuilder

The following example shows a more sophisticated configuration, including SSL and timeouts, that uses 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

For more detailed client configuration tweaks, see LettuceClientConfiguration.

Lettuce 与 Netty 的 native transports 集成,让你可以使用 Unix 域套接字与 Redis 通信。请务必包含与运行时环境匹配的适当原生传输依赖项。以下示例演示如何为 /var/run/redis.sock 处的 Unix 域套接字创建 Lettuce Connection 工厂:

Lettuce integrates with Netty’s native transports, letting you use Unix domain sockets to communicate with Redis. Make sure to include the appropriate native transport dependencies that match your runtime environment. The following example shows how to create a Lettuce Connection factory for a Unix domain socket at /var/run/redis.sock:

@Configuration
class AppConfig {

  @Bean
  public LettuceConnectionFactory redisConnectionFactory() {

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

Netty 当前支持 epoll(Linux)和 kqueue(BSD/macOS)接口用于操作系统本机传输。

Netty currently supports the epoll (Linux) and kqueue (BSD/macOS) interfaces for OS-native transport.

Configuring the Jedis Connector

Jedis 是由 Spring Data Redis 模块通过 org.springframework.data.redis.connection.jedis 包支持的社区驱动连接器。

Jedis is a community-driven connector supported by the Spring Data Redis module through the org.springframework.data.redis.connection.jedis package.

Add the following to the pom.xml files dependencies element:
<dependencies>

  <!-- other dependency elements omitted -->

  <dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>{jedis}</version>
  </dependency>

</dependencies>

在其最简单的形式中,Jedis 配置如下:

In its simplest form, the Jedis configuration looks as follow:

@Configuration
class AppConfig {

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

然而,对于生产用途,你可能想要微调诸如主机或密码之类的设置,如下面的示例中所示:

For production use, however, you might want to tweak settings such as the host or password, as shown in the following example:

@Configuration
class RedisConfiguration {

  @Bean
  public JedisConnectionFactory redisConnectionFactory() {

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