Lettuce 指南
将 Lettuce 应用程序连接到 Redis 数据库
安装 Redis 和 Redis 客户端,然后将 Lettuce 应用程序连接到 Redis 数据库。
Lettuce
Lettuce 通过异步和响应式 API 提供了一种功能强大且高效的方式与 Redis 交互。通过利用这些功能,你可以构建高性能、可扩展的 Java 应用程序,充分利用 Redis 的功能。
安装
若要将 Lettuce 作为依赖项包含在应用程序中,请按如下所示编辑相应的依赖项文件。
如果你使用 Maven,请将以下依赖项添加到你的 pom.xml
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>6.3.2.RELEASE</version> <!-- Check for the latest version on Maven Central -->
</dependency>
如果你使用 Gradle,请将此行包含在你的 build.gradle
文件中
dependencies {
compile 'io.lettuce:lettuce-core:6.3.2.RELEASE
}
如果你希望直接使用 JAR 文件,请从 Maven Central 或任何其他 Maven 存储库下载最新的 Lettuce,以及可选的 Apache Commons Pool2 JAR 文件。
若要从源代码构建,请参阅 Lettuce 源代码 GitHub 存储库 上的说明。
连接
首先创建一个到 Redis 服务器的连接。使用 Lettuce 有多种方法可以实现此目的。以下列出几种方法。
异步连接
package org.example;
import java.util.*;
import java.util.concurrent.ExecutionException;
import io.lettuce.core.*;
import io.lettuce.core.api.async.RedisAsyncCommands;
import io.lettuce.core.api.StatefulRedisConnection;
public class Async {
public static void main(String[] args) {
RedisClient redisClient = RedisClient.create("redis://localhost:6379");
try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
RedisAsyncCommands<String, String> asyncCommands = connection.async();
// Asynchronously store & retrieve a simple string
asyncCommands.set("foo", "bar").get();
System.out.println(asyncCommands.get("foo").get()); // prints bar
// Asynchronously store key-value pairs in a hash directly
Map<String, String> hash = new HashMap<>();
hash.put("name", "John");
hash.put("surname", "Smith");
hash.put("company", "Redis");
hash.put("age", "29");
asyncCommands.hset("user-session:123", hash).get();
System.out.println(asyncCommands.hgetall("user-session:123").get());
// Prints: {name=John, surname=Smith, company=Redis, age=29}
} catch (ExecutionException | InterruptedException e) {
throw new RuntimeException(e);
} finally {
redisClient.shutdown();
}
}
}
在 参考指南 中了解有关异步 Lettuce API 的更多信息。
响应式连接
package org.example;
import java.util.*;
import io.lettuce.core.*;
import io.lettuce.core.api.reactive.RedisReactiveCommands;
import io.lettuce.core.api.StatefulRedisConnection;
public class Main {
public static void main(String[] args) {
RedisClient redisClient = RedisClient.create("redis://localhost:6379");
try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
RedisReactiveCommands<String, String> reactiveCommands = connection.reactive();
// Reactively store & retrieve a simple string
reactiveCommands.set("foo", "bar").block();
reactiveCommands.get("foo").doOnNext(System.out::println).block(); // prints bar
// Reactively store key-value pairs in a hash directly
Map<String, String> hash = new HashMap<>();
hash.put("name", "John");
hash.put("surname", "Smith");
hash.put("company", "Redis");
hash.put("age", "29");
reactiveCommands.hset("user-session:124", hash).then(
reactiveCommands.hgetall("user-session:124")
.collectMap(KeyValue::getKey, KeyValue::getValue).doOnNext(System.out::println))
.block();
// Prints: {surname=Smith, name=John, company=Redis, age=29}
} finally {
redisClient.shutdown();
}
}
}
在 参考指南 中了解有关响应式 Lettuce API 的更多信息。
Redis 集群连接
import io.lettuce.core.RedisURI;
import io.lettuce.core.cluster.RedisClusterClient;
import io.lettuce.core.cluster.api.StatefulRedisClusterConnection;
import io.lettuce.core.cluster.api.async.RedisAdvancedClusterAsyncCommands;
// ...
RedisURI redisUri = RedisURI.Builder.redis("localhost").withPassword("authentication").build();
RedisClusterClient clusterClient = RedisClusterClient.create(redisUri);
StatefulRedisClusterConnection<String, String> connection = clusterClient.connect();
RedisAdvancedClusterAsyncCommands<String, String> commands = connection.async();
// ...
connection.close();
clusterClient.shutdown();
TLS 连接
在部署应用程序时,请使用 TLS 并遵循 Redis 安全指南。
RedisURI redisUri = RedisURI.Builder.redis("localhost")
.withSsl(true)
.withPassword("secret!") // use your Redis password
.build();
RedisClient client = RedisClient.create(redisUri);
Lettuce 中的连接管理
Lettuce 使用 ClientResources
来高效管理共享资源,如事件循环组和线程池。对于连接池,Lettuce 利用 RedisClient
或 RedisClusterClient
,它们可以高效地处理多个并发连接。
使用 Lettuce 的典型方法是创建一个 RedisClient
实例并重复使用它来建立与 Redis 服务器的连接。这些连接是多路复用的;也就是说,可以在单个或少量连接上并发运行多个命令,从而降低了显式池化的重要性。
Lettuce 提供了与 Lettuce 异步连接方法一起使用的池配置。
package org.example;
import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisURI;
import io.lettuce.core.TransactionResult;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.async.RedisAsyncCommands;
import io.lettuce.core.codec.StringCodec;
import io.lettuce.core.support.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
public class Pool {
public static void main(String[] args) {
RedisClient client = RedisClient.create();
String host = "localhost";
int port = 6379;
CompletionStage<BoundedAsyncPool<StatefulRedisConnection<String, String>>> poolFuture
= AsyncConnectionPoolSupport.createBoundedObjectPoolAsync(
() -> client.connectAsync(StringCodec.UTF8, RedisURI.create(host, port)),
BoundedPoolConfig.create());
// await poolFuture initialization to avoid NoSuchElementException: Pool exhausted when starting your application
AsyncPool<StatefulRedisConnection<String, String>> pool = poolFuture.toCompletableFuture()
.join();
// execute work
CompletableFuture<TransactionResult> transactionResult = pool.acquire()
.thenCompose(connection -> {
RedisAsyncCommands<String, String> async = connection.async();
async.multi();
async.set("key", "value");
async.set("key2", "value2");
System.out.println("Executed commands in pipeline");
return async.exec().whenComplete((s, throwable) -> pool.release(connection));
});
transactionResult.join();
// terminating
pool.closeAsync();
// after pool completion
client.shutdownAsync();
}
}
在此设置中,LettuceConnectionFactory
是您需要实现的自定义类,它遵循 Apache Commons Pool 的 PooledObjectFactory
接口,以管理池化 StatefulRedisConnection
对象的生命周期事件。
DNS 缓存和 Redis
当您连接到具有多个端点的 Redis 数据库(例如 Redis Enterprise Active-Active)时,建议禁用 JVM 的 DNS 缓存以跨多个端点平衡负载请求。
您可以在应用程序的代码中使用以下代码段执行此操作
java.security.Security.setProperty("networkaddress.cache.ttl","0");
java.security.Security.setProperty("networkaddress.cache.negative.ttl", "0");