Redis 扩展参考指南
1. 使用 Redis 客户端
如果要使用此扩展,需要首先添加 io.quarkus:quarkus-redis
扩展。在您的 pom.xml
文件中,添加
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-redis-client</artifactId>
</dependency>
implementation("io.quarkus:quarkus-redis-client")
使用此依赖项,您可以注入 Redis 客户端或数据源(高级、类型安全 API),例如
import io.quarkus.redis.datasource.RedisDataSource;
// ...
@Inject RedisAPI lowLevelClient;
@Inject RedisDataSource highLevelApi;
有关 quarkus-redis 扩展提供的各种 API 的更多详细信息,请参见 一个扩展,多个 API 部分。
要使用 Redis 作为缓存后端,请参阅Redis 缓存后端参考。 |
2. 一个扩展,多个 API
此扩展提供了多种与 Redis 交互的方式
-
低级 Vert.x 客户端:它是一个完全响应式、非阻塞和异步的客户端。更多详细信息请参见 Vert.x Redis 客户端文档。公开了两个 API:
io.vertx.redis.client.Redis
和io.vertx.redis.client.RedisAPI
。通常您会使用后者,除非您需要自己管理连接。 -
Vert.x API 的 低级 Mutiny 变体:与前一个不同,它公开了一个 Mutiny API,并提供响应式和命令式方法(后缀为
andAwait()
)。公开了两个 API:io.vertx.mutiny.redis.client.Redis
和io.vertx.mutiny.redis.client.RedisAPI
。通常您会使用后者,除非您需要自己管理连接。 -
高级 响应式数据源:一个类型安全、高级 API,用于与 Redis 交互。此 API 完全是响应式的和异步的。它公开了一个 Mutiny API。它公开了
io.quarkus.redis.datasource.ReactiveRedisDataSource
接口。 -
高级 命令式数据源:一个类型安全、高级 API,用于与 Redis 交互。它是响应式数据源的命令式变体。它公开了
io.quarkus.redis.datasource.RedisDataSource
接口。
为了帮助您选择适合您的 API,这里有一些建议
-
如果您正在构建一个与 Redis 集成的命令式(经典)Quarkus 应用程序:使用
io.quarkus.redis.datasource.RedisDataSource
。 -
如果您正在构建一个与 Redis 集成的响应式 Quarkus 应用程序:使用
io.quarkus.redis.datasource.ReactiveRedisDataSource
。 -
如果您需要细粒度控制,或者以通用方式执行命令:使用
io.vertx.mutiny.redis.client.RedisAPI
-
如果您有现有的 Vert.x 代码,请使用
io.vertx.redis.client.RedisAPI
-
如果您需要发出自定义命令,您可以使用数据源(响应式或命令式)或
io.vertx.mutiny.redis.client.Redis
。
3. 注入默认和命名客户端
此扩展允许您配置默认 Redis 客户端/数据源或命名客户端/数据源。后者在您需要连接到多个 Redis 实例时至关重要。
默认连接使用 quarkus.redis.*
属性配置。例如,要配置默认 Redis 客户端,请使用
quarkus.redis.hosts=redis:///
使用默认连接时,您可以使用普通 @Inject
注入各种 API
@ApplicationScoped
public class RedisExample {
@Inject ReactiveRedisDataSource reactiveDataSource;
@Inject RedisDataSource redisDataSource;
@Inject RedisAPI redisAPI;
// ...
}
通常,您只注入一个;前面的代码片段只是一个示例。 |
命名客户端使用 quarkus.redis.<name>.*
属性配置
quarkus.redis.my-redis-1.hosts=redis:///
quarkus.redis.my-redis-2.hosts=redis://my-other-redis:6379
要访问 API,您需要使用 @RedisClientName
限定符
@ApplicationScoped
public class RedisExample {
@Inject @RedisClientName("my-redis-1") ReactiveRedisDataSource reactiveDataSource;
@Inject @RedisClientName("my-redis-2") RedisDataSource redisDataSource;
// ...
}
使用 @RedisClientName 时,您可以省略 @Inject 注释。 |
4. 连接到 Redis 服务器
Redis 扩展可以在 4 种不同的模式下运行
-
简单客户端(可能是大多数用户需要的)。
-
Sentinel(在 High Availability 模式下使用 Redis 时)。
-
集群(在 Clustered 模式下使用 Redis 时)。
-
复制(单分片,一个节点写入,多个读取)。
连接 URL 使用 quarkus.redis.hosts
(或 quarkus.redis.<name>.hosts
)配置,如下所示
quarkus.redis.hosts=redis://[:password@]host[:port][/db-number]
4.1. 使用 Unix Socket
使用 unix-socket 时,您需要
quarkus.redis.hosts=unix://[:password@]/domain/docker.sock[?select=db-number]
4.2. 使用 Sentinel 模式
使用 Sentinel 时,您需要传递多个主机 URL并将客户端类型配置为 sentinel
quarkus.redis.hosts=redis://:5000,redis://:5001,redis://:5002
quarkus.redis.client-type=sentinel
# Optional
quarkus.redis.master-name=my-sentinel # Default is mymaster
quarkus.redis.role=master # master is the default
这里的主机 URL 必须是 sentinel 服务器。客户端将使用 master-name
作为“master set”的标识符,从其中一个 sentinel 获取实际 Redis 服务器(主服务器或副本,取决于 role
)的 URL。
请注意,实际上您永远不会想要配置 quarkus.redis.role=sentinel
。此设置意味着 Redis 客户端将直接在一个 sentinel 服务器上执行命令,而不是在由 sentinel 保护的实际 Redis 服务器上执行命令。
4.2.1. 自动故障转移
在 sentinel 模式下,可以配置主连接的自动故障转移
quarkus.redis.auto-failover=true
如果启用,sentinel 客户端将额外创建一个与一个 sentinel 节点的连接,并监视故障转移事件。当选出新的主服务器时,所有与旧主服务器的连接都会自动关闭,并创建与新主服务器的新连接。自动故障转移对于执行常规命令的连接有意义,但对于用于订阅 Redis pub/sub 通道的连接没有意义。
请注意,在旧主服务器发生故障和新主服务器被选出之间有一个短暂的时间段,在此期间现有连接将暂时失败所有操作。在新主服务器被选出后,连接将自动故障转移并再次开始工作。
4.3. 使用集群模式
在集群模式下使用 Redis 时,您需要传递多个主机 URL,将客户端类型配置为 cluster
并配置 replicas
模式
quarkus.redis.hosts=redis://:7000,redis://:7001,redis://:7002
quarkus.redis.client-type=cluster
# Optional
quarkus.redis.replicas=share # defaults to "never"
这里的主机 URL 必须是一些集群成员。不需要配置所有集群成员,因为客户端将从一个已知的服务器获取完整的集群拓扑。但是,建议至少配置 2 或 3 个节点,而不仅仅是 1 个。
默认情况下,所有命令都发送到主节点(如果命令有一个键,则它是拥有该键的分片的主节点,否则它是一个随机主节点)。可以配置 Redis 客户端将只读命令(查询)发送到副本节点。将 quarkus.redis.replicas
配置属性设置为
-
never
:从不使用副本节点,始终将查询发送到主节点(这是默认设置) -
always
:始终使用副本节点(如果分片中有多个副本,则随机选择一个),从不将查询发送到主节点 -
share
:使用主节点和副本节点来执行查询(每个查询的特定节点是随机选择的)
请注意,Redis 中的复制是异步的,因此副本节点可能会滞后于其主节点。
4.4. 使用复制模式
使用复制模式时,您需要传递单个主机 URL 并将类型配置为 replication
quarkus.redis.hosts=redis://:7000
quarkus.redis.client-type=replication
# Optional
quarkus.redis.replicas=share # defaults to "never"
默认情况下,所有命令都发送到主节点。可以配置 Redis 客户端将只读命令(查询)发送到副本节点。将 quarkus.redis.replicas
配置属性设置为
-
never
:从不使用副本节点,始终将查询发送到主节点(这是默认设置) -
always
:始终使用副本节点(如果有一个以上的副本,则随机选择一个),从不将查询发送到主节点 -
share
:使用主节点和副本节点来执行查询(每个查询的特定节点是随机选择的)
请注意,Redis 中的复制是异步的,因此副本节点可能会滞后于主节点。
4.4.1. 静态拓扑
在复制模式下,可以重新配置 Redis 客户端以跳过拓扑的自动发现
quarkus.redis.topology=static
使用静态拓扑,配置中的第一个节点被假定为主节点,而其余节点被假定为副本。节点未经过验证;应用程序开发人员有责任确保静态配置正确。
请注意,通常首选拓扑的自动发现。仅在必要时才应使用静态配置。一个这样的例子是Amazon Elasticache for Redis (禁用集群模式),其中
-
主节点应设置为主终端节点,并且
-
一个副本节点应设置为读取器终端节点。
请注意,Elasticache for Redis (禁用集群模式) 的读取器终端节点是一个域名,它解析为指向其中一个副本的 CNAME 记录。读取器终端节点解析到的 CNAME 记录会随着时间而变化。这种基于 DNS 的负载平衡与 DNS 解析缓存和连接池配合不好。因此,某些副本很可能未得到充分利用。 |
4.5. 连接到 Redis Cloud
要连接到 redis cloud,您需要以下属性
quarkus.redis.hosts=<the redis cloud url such as redis://redis-12436.c14.us-east-1-3.ec2.cloud.redislabs.com:12436>
quarkus.redis.password=<the password>
4.6. 使用 TLS
要使用 TLS,您需要
-
设置
quarkus.redis.tls.enabled=true
属性或使用 TLS 注册表(推荐) -
确保您的 URL 以
rediss://
开头(带有两个s
)
使用 TLS 注册表时,您需要使用命名配置以避免与其他 TLS 配置冲突
quarkus.tls.redis.trust-store.p12.path=client.p12
quarkus.tls.redis.trust-store.p12.password=secret
quarkus.redis.tls-configuration-name=redis # Reference the named configuration
默认主机名验证器设置为 NONE ,这意味着它不验证主机名。您可以通过设置 quarkus.redis.tls.hostname-verification-algorithm 属性来更改此行为,例如设置为 HTTPS 。 |
5. 使用 Redis 数据源
Quarkus 在 Redis 之上公开了一个高级 API。此 API 是类型安全的,并围绕组的概念构建,该概念继承自 Redis 命令组织。此 API 使您可以更方便和安全地执行 Redis 命令。
5.1. 注入数据源
对于每个配置的 Redis 客户端,公开了两个 Redis 数据源
-
io.quarkus.redis.datasource.RedisDataSource
- 命令式(阻塞)Redis 数据源。每个操作都会阻塞,直到收到响应或达到超时 -
io.quarkus.redis.datasource.ReactiveRedisDataSource
- 响应式 Redis 数据源,返回Uni<X>
或Multi<X>
。
如果您配置了默认 Redis 客户端,则可以使用以下方式注入数据源
@Inject RedisDataSource defaultRedisDataSource;
@Inject ReactiveRedisDataSource defaultReactiveRedisDataSource;
如果您配置了命名 Redis 客户端,则需要使用 io.quarkus.redis.RedisClientName
限定符来选择正确的客户端
@RedisClientName("my-redis") RedisDataSource myRedisDataSource;
@RedisClientName("my-redis") ReactiveRedisDataSource myReactiveRedisDataSource;
使用阻塞变体时,可以使用以下方式配置默认超时
quarkus.redis.timeout=5s
quarkus.redis.my-redis.timeout=5s
默认超时配置为 10 秒。
关于委托
阻塞数据源 ( |
5.1.1. 数据源组
如上所述,API 分为几个组
-
bitmap -
.bitmap()
-
key (通用) -
.key()
-
geo -
.geo(memberType)
-
hash -
.hash(`valueType)
-
hyperloglog -
.hyperloglog(memberType)
-
list -
.list(memberType)
-
pubsub -
pubsub()
-
set -
.set(memberType)
-
sorted-set -
.sortedSet(memberType)
-
string -
.value(valueType)
-
stream -
.stream(`valueType
) -
transactions -
withTransaction
-
json -
.json()
(需要在服务器端使用 RedisJSON 模块) -
bloom -
.bloom()
(需要在服务器端使用 RedisBloom 模块) -
cuckoo -
.cuckoo()
(需要在服务器端使用 rRedisBloom 模块,该模块还提供 cuckoo 过滤器命令) -
count-min -
.countmin()
(需要在服务器端使用 RedisBloom 模块,该模块还提供 count-min 过滤器命令) -
top-k -
.topk()
(需要在服务器端使用 RedisBloom 模块,该模块还提供 top-k 过滤器命令) -
graph -
.graph()
(需要在服务器端使用 RedisGraph 模块)。这些命令被标记为实验性的。此外,Redis 已声明该模块生命周期结束。 -
search -
.search()
(需要在服务器端使用 RedisSearch 模块)。 -
auto-suggest -
.autosuggest()
(需要在服务器端使用 RedisSearch 模块)。 -
time-series -
.timeseries()
(需要在服务器端使用 Redis Time Series 模块)。
这些命令被标记为实验性的,因为我们需要反馈才能使它们稳定。
这些方法中的每一种都返回一个对象,该对象允许您执行与该组相关的命令。以下代码片段演示了如何使用哈希组
@ApplicationScoped
public class MyRedisService {
private static final String MY_KEY = "my-key";
private final HashCommands<String, String, Person> commands;
public MyRedisService(RedisDataSource ds) { (1)
commands = ds.hash(Person.class); (2)
}
public void set(String field, Person value) {
commands.hset(MY_KEY, field, value); (3)
}
public Person get(String field) {
return commands.hget(MY_KEY, field); (4)
}
}
1 | 在构造函数中注入 RedisDataSource |
2 | 创建 HashCommands 对象。此对象具有三个类型参数:键的类型、字段的类型和成员的类型 |
3 | 使用创建的 commands 将字段 field 与值 value 相关联 |
4 | 使用创建的 commands 检索字段 field 值。 |
5.4. 自定义编解码器
您可以通过提供实现 io.quarkus.redis.datasource.codecs.Codec
接口的 CDI bean 来注册自定义编解码器
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import jakarta.enterprise.context.ApplicationScoped;
import io.quarkus.redis.datasource.codecs.Codec;
@ApplicationScoped
public class PersonCodec implements Codec {
@Override
public boolean canHandle(Type clazz) {
return clazz.equals(Person.class);
}
@Override
public byte[] encode(Object item) {
var p = (Person) item;
return (p.firstName + ";" + p.lastName.toUpperCase()).getBytes(StandardCharsets.UTF_8);
}
@Override
public Object decode(byte[] item) {
var value = new String(item, StandardCharsets.UTF_8);
var segments = value.split(";");
return new Person(segments[0], segments[1]);
}
}
调用 canHandle
方法以检查编解码器是否可以处理特定类型。在 encode
方法中接收到的参数与该类型匹配。decode
方法返回的对象也必须与该类型匹配。
5.5. 使用类型引用
每个组都可以使用 Class
或 TypeReference
对象进行配置。在处理 Java 泛型时,TypeReference
很有用
@ApplicationScoped
public class MyRedisService {
private static final String MY_KEY = "my-key";
private final HashCommands<String, String, List<Person>> commands;
public MyRedisService(RedisDataSource ds) {
commands = ds.hash(new TypeReference<List<Person>>(){});
}
public void set(String field, List<Person> value) {
commands.hset(MY_KEY, field, value);
}
public List<Person> get(String field) {
return commands.hget(MY_KEY, field);
}
}
使用事务时不能使用类型引用。这是一个已知的限制。 |
5.6. 使用 value
组操作缓存和二进制数据
value
组用于操作 Redis 字符串。因此,此组不仅限于 Java 字符串,还可以用于整数(如计数器)或二进制内容(如图像)。
5.6.1. 使用缓存值
您可以使用 Redis 作为缓存,使用 setex
命令,该命令将给定的值存储到给定的键,持续给定的时间。以下代码片段显示了如何使用此类命令将 BusinessObject
存储 1 秒。
@ApplicationScoped
public static class MyRedisCache {
private final ValueCommands<String, BusinessObject> commands;
public MyRedisCache(RedisDataSource ds) {
commands = ds.value(BusinessObject.class);
}
public BusinessObject get(String key) {
return commands.get(key);
}
public void set(String key, BusinessObject bo) {
commands.setex(key, 1, bo); // Expires after 1 second
}
}
您可以使用 setnx
方法仅在没有为给定键存储值时才设置该值。
key 组提供了对每个键的到期和 ttl 的更细粒度控制。 |
|
5.6.2. 存储二进制数据
Redis 字符串可用于存储二进制数据,例如图像。在这种情况下,我们将使用 byte[]
作为值类型
@ApplicationScoped
public static class MyBinaryRepository {
private final ValueCommands<String, byte[]> commands;
public MyBinaryRepository(RedisDataSource ds) {
commands = ds.value(byte[].class);
}
public byte[] get(String key) {
byte[] bytes = commands.get(key);
if (bytes == null) {
throw new NoSuchElementException("`" + key + "` not found");
}
return bytes;
}
public void add(String key, byte[] bytes) {
commands.set(key, bytes);
}
public void addIfAbsent(String key, byte[] bytes) {
commands.setnx(key, bytes);
}
}
5.6.3. 存储计数器
您可以在 Redis 中存储计数器,如下所示
@ApplicationScoped
public static class MyRedisCounter {
private final ValueCommands<String, Long> commands;
public MyRedisCounter(RedisDataSource ds) {
commands = ds.value(Long.class); (1)
}
public long get(String key) {
Long l = commands.get(key); (2)
if (l == null) {
return 0L;
}
return l;
}
public void incr(String key) {
commands.incr(key); (3)
}
}
1 | 检索命令。这次我们将操作 Long 值 |
2 | 检索与给定 key 关联的计数器。当没有存储计数器时返回 0L 。 |
3 | 递增值。如果没有为该键存储计数器,则 incr 命令将 0 视为值(因此 incr 将值设置为 1)。 |
还有其他一些方法可以用来操作计数器,例如
-
incrby
- 允许设置增量值(正或负) -
incrbyfloat
- 允许将增量值设置为 float/double(存储的值将为 double) -
set
- 如果需要,设置初始值 -
decr
和decrby
- 允许递减存储的值
5.6.4. 使用 pub/sub 通信
Redis 允许将消息发送到通道并监听这些消息。这些功能可从 pubsub
组获得。
以下代码片段显示了一个缓存如何在每次 set
后发出 Notification
,以及订阅者如何接收通知。
public static final class Notification {
public String key;
public BusinessObject bo;
public Notification() {
}
public Notification(String key, BusinessObject bo) {
this.key = key;
this.bo = bo;
}
}
@ApplicationScoped
@Startup // We want to create the bean instance on startup to subscribe to the channel.
public static class MySubscriber implements Consumer<Notification> {
private final PubSubCommands<Notification> pub;
private final PubSubCommands.RedisSubscriber subscriber;
public MySubscriber(RedisDataSource ds) {
pub = ds.pubsub(Notification.class);
subscriber = pub.subscribe("notifications", this);
}
@Override
public void accept(Notification notification) {
// Receive the notification
}
@PreDestroy
public void terminate() {
subscriber.unsubscribe(); // Unsubscribe from all subscribed channels
}
}
@ApplicationScoped
public static class MyCache {
private final ValueCommands<String, BusinessObject> commands;
private final PubSubCommands<Notification> pub;
public MyCache(RedisDataSource ds) {
commands = ds.value(BusinessObject.class);
pub = ds.pubsub(Notification.class);
}
public BusinessObject get(String key) {
return commands.get(key);
}
public void set(String key, BusinessObject bo) {
commands.set(key, bo);
pub.publish("notifications", new Notification(key, bo));
}
}
5.6.5. 使用 Redis 事务
Redis 事务与关系数据库事务略有不同。Redis 事务是一批一起执行的命令。
Redis 事务可以监视一组键,如果其中一个键在事务执行期间更新,则会丢弃该事务。
在事务中排队的命令不会在整个事务执行之前执行。这意味着您无法在事务期间检索结果。结果会累积在 TransactionResult
对象中,您将在事务完成后访问该对象。此对象包含事务是否成功或被丢弃,以及在前者中每个命令的结果(按命令顺序索引)。
要启动事务,您可以使用 withTransaction
方法。此方法接收 Consumer<TransactionalRedisDataSource>
,它遵循与常规 RedisDataSource
相同的 API,只是命令返回 void
(响应式变体返回 Uni<Void>
)。当该使用者返回时,事务被执行。
以下代码片段显示了如何创建执行两个相关写入的事务
@Inject RedisDataSource ds;
// ...
TransactionResult result = ds.withTransaction(tx -> {
TransactionalHashCommands<String, String, String> hash = tx.hash(String.class);
hash.hset(KEY, "field-1", "hello");
hash.hset(KEY, "field-2", "hello");
});
接收到的 tx
对象也可用于丢弃事务,使用:tx.discard();
。返回的 TransactionResult
允许您检索每个命令的结果。
使用数据源的响应式变体时,传递的回调是 Function<ReactiveTransactionalRedisDataSource, Uni<Void>>
@Inject ReactiveRedisDataSource ds;
// ...
Uni<TransactionResult> result = ds.withTransaction(tx -> {
ReactiveTransactionalHashCommands<String, String, String> hash = tx.hash(String.class);
return hash.hset(KEY, "field-1", "hello")
.chain(() -> hash.hset(KEY, "field-2", "hello"));
});
事务执行可以由键来调节。如果在事务执行期间修改了传递的键,则事务将被丢弃。键作为 String
作为 withTransaction
方法的第二个参数传递
TransactionResult result = ds.withTransaction(tx -> {
TransactionalHashCommands<String, String, String> hash = tx.hash(String.class);
hash.hset(KEY, "field-1", "hello");
hash.hset(KEY, "field-2", "hello");
}, KEY);
您不能从事务中使用 pub/sub 功能。 |
5.6.6. 实现乐观锁定模式
要使用乐观锁定,您需要使用 withTransaction
方法的一个变体,该变体允许在事务开始之前执行代码。换句话说,它将按以下方式执行
WATCH key
// Pre-transaction block
// ....
// Produce a result
MULTI
// In transaction code, receive the result produced by the pre-transaction block.
EXEC
例如,如果您只需要在字段存在时才更新哈希中的值,您将使用以下 API
OptimisticLockingTransactionResult<Boolean> result = blocking.withTransaction(ds -> {
// The pre-transaction block:
HashCommands<String, String, String> hashCommands = ds.hash(String.class);
return hashCommands.hexists(key, "field"); // Produce a result (boolean in this case)
},
(exists, tx) -> { // The transactional block, receives the result and the transactional data source
if (exists) {
tx.hash(String.class).hset(key, "field", "new value");
} else {
tx.discard();
}
},
key); // The watched key
如果在事务前或事务块执行之前或期间触摸了其中一个监视的键,则事务将被中止。事务前块产生一个结果,事务块可以使用该结果。这种构造是必要的,因为在事务中,命令不会产生结果。结果只能在事务执行后检索。
事务前和事务块在同一个 Redis 连接上调用。因此,事务前块必须使用传递的数据源来执行命令。因此,这些命令是从该连接发出的。这些命令不得修改监视的键。
如果事务前块抛出异常(或在使用响应式 API 时产生失败),则事务将被中止。
6. 将数据预加载到 Redis 中
在启动时,您可以配置 Redis 客户端将数据预加载到 Redis 数据库中。
6.1. 配置加载脚本
使用以下方式指定要加载的加载脚本
quarkus.redis.load-script=import.redis # import.redis is the default in dev mode, no-file is the default in production mode
quarkus.redis.my-redis.load-script=actors.redis, movies.redis
load-script 是一个构建时属性,不能在运行时被覆盖。 |
请注意,每个客户端都可以有不同的脚本,甚至是脚本列表。对于列表的情况,数据按照列表顺序导入(例如,对于 my-redis
客户端,首先导入 actors.redis
,然后导入 movies.redis
)。
6.2. 编写加载脚本
.redis
文件遵循每行一个命令的格式
# Line starting with # and -- are ignored, as well as empty lines
-- One command per line:
HSET foo field1 abc field2 123
-- Parameters with spaces must be wrapped into single or double quotes
HSET bar field1 "abc def" field2 '123 456 '
-- Parameters with double quotes must be wrapped into single quotes and the opposite
SET key1 'A value using "double-quotes"'
SET key2 "A value using 'single-quotes'"
Quarkus 批处理来自单个文件的所有命令并发送所有命令。如果出现任何错误,加载过程将失败,但先前的指令可能已执行。为避免这种情况,您可以将命令包装到 Redis 事务中
-- Run inside a transaction
MULTI
SET key value
SET space:key 'another value'
INCR counter
EXEC
7. 使用 Vert.x redis 客户端
除了高级 API 之外,您还可以在代码中直接使用 Vertx Redis 客户端。Vert.x Redis 客户端的文档可在 Vert.x Web 站点上找到。
8. 以编程方式配置 Redis 主机
RedisHostsProvider
以编程方式提供 redis 主机。这允许配置来自其他来源的 redis 连接密码等属性。
这很有用,因为它消除了在 application.properties 中存储敏感数据的需要。 |
@ApplicationScoped
@Identifier("hosts-provider") // the name of the host provider
public class ExampleRedisHostProvider implements RedisHostsProvider {
@Override
public Set<URI> getHosts() {
// do stuff to get the host
String host = "redis://:6379/3";
return Collections.singleton(URI.create(host));
}
}
主机提供程序可用于配置 redis 客户端,如下所示
quarkus.redis.hosts-provider-name=hosts-provider
9. 以编程方式自定义 Redis 选项
您可以公开一个 bean,该 bean 实现 io.quarkus.redis.client.RedisOptionsCustomizer
接口以自定义 Redis 客户端选项。为每个配置的 Redis 客户端调用 bean
@ApplicationScoped
public static class MyExampleCustomizer implements RedisOptionsCustomizer {
@Override
public void customize(String clientName, RedisOptions options) {
if (clientName.equalsIgnoreCase("my-redis")
|| clientName.equalsIgnoreCase(RedisConfig.DEFAULT_CLIENT_NAME)) {
// modify the given options
} else {
throw new IllegalStateException("Unknown client name: " + clientName);
}
}
}
9.1. 使用 Redis Dev Services
请参阅 Redis Dev Service。
10. 配置 Redis 可观察性
10.1. 启用运行状况检查
如果您正在使用 quarkus-smallrye-health
扩展,quarkus-redis
将自动添加就绪状态运行状况检查以验证与 Redis 服务器的连接。
因此,当您访问应用程序的 /q/health/ready
终端节点时,您将获得有关连接验证状态的信息。
可以通过在 application.properties
中将 quarkus.redis.health.enabled
属性设置为 false
来禁用此行为。
10.2. 启用指标
当应用程序也使用 quarkus-micrometer
扩展时,将自动启用 Redis 客户端指标。Micrometer 收集应用程序实现的所有 Redis 客户端的指标。
例如,如果您将指标导出到 Prometheus,您将得到
# HELP redis_commands_duration_seconds The duration of the operations (commands of batches
# TYPE redis_commands_duration_seconds summary
redis_commands_duration_seconds_count{client_name="<default>",} 3.0
redis_commands_duration_seconds_sum{client_name="<default>",} 0.047500042
# HELP redis_commands_duration_seconds_max The duration of the operations (commands of batches
# TYPE redis_commands_duration_seconds_max gauge
redis_commands_duration_seconds_max{client_name="<default>",} 0.033273167
# HELP redis_pool_active The number of resources from the pool currently used
# TYPE redis_pool_active gauge
redis_pool_active{pool_name="<default>",pool_type="redis",} 0.0
# HELP redis_pool_ratio Pool usage ratio
# TYPE redis_pool_ratio gauge
redis_pool_ratio{pool_name="<default>",pool_type="redis",} 0.0
# HELP redis_pool_queue_size Number of pending elements in the waiting queue
# TYPE redis_pool_queue_size gauge
redis_pool_queue_size{pool_name="<default>",pool_type="redis",} 0.0
# HELP redis_commands_failure_total The number of operations (commands or batches) that have been failed
# TYPE redis_commands_failure_total counter
redis_commands_failure_total{client_name="<default>",} 0.0
# HELP redis_commands_success_total The number of operations (commands or batches) that have been executed successfully
# TYPE redis_commands_success_total counter
redis_commands_success_total{client_name="<default>",} 3.0
# HELP redis_pool_idle The number of resources from the pool currently used
# TYPE redis_pool_idle gauge
redis_pool_idle{pool_name="<default>",pool_type="redis",} 6.0
# HELP redis_pool_completed_total Number of times resources from the pool have been acquired
# TYPE redis_pool_completed_total counter
redis_pool_completed_total{pool_name="<default>",pool_type="redis",} 3.0
# HELP redis_commands_count_total The number of operations (commands or batches) executed
# TYPE redis_commands_count_total counter
redis_commands_count_total{client_name="<default>",} 3.0
# HELP redis_pool_usage_seconds Time spent using resources from the pool
# TYPE redis_pool_usage_seconds summary
redis_pool_usage_seconds_count{pool_name="<default>",pool_type="redis",} 3.0
redis_pool_usage_seconds_sum{pool_name="<default>",pool_type="redis",} 0.024381375
# HELP redis_pool_usage_seconds_max Time spent using resources from the pool
# TYPE redis_pool_usage_seconds_max gauge
redis_pool_usage_seconds_max{pool_name="<default>",pool_type="redis",} 0.010671542
# HELP redis_pool_queue_delay_seconds Time spent in the waiting queue before being processed
# TYPE redis_pool_queue_delay_seconds summary
redis_pool_queue_delay_seconds_count{pool_name="<default>",pool_type="redis",} 3.0
redis_pool_queue_delay_seconds_sum{pool_name="<default>",pool_type="redis",} 0.022341249
# HELP redis_pool_queue_delay_seconds_max Time spent in the waiting queue before being processed
# TYPE redis_pool_queue_delay_seconds_max gauge
redis_pool_queue_delay_seconds_max{pool_name="<default>",pool_type="redis",} 0.021926083
Redis 客户端名称可以在标签中找到。
这些指标包含 Redis 连接池指标 (redis_pool_*
) 和有关命令执行的指标 (redis_commands_*
),例如命令数、成功、失败和持续时间。
11. 配置参考
构建时固定的配置属性 - 所有其他配置属性都可以在运行时覆盖
配置属性 |
类型 |
默认 |
---|---|---|
允许将数据预加载到 Redis 服务器中的文件列表。该文件的格式如下
环境变量: 显示更多 |
字符串列表 |
|
使用 环境变量: 显示更多 |
布尔值 |
|
使用 环境变量: 显示更多 |
布尔值 |
|
如果 smallrye-health 扩展存在,是否发布健康检查。 环境变量: 显示更多 |
布尔值 |
|
连接到 Redis 服务器时要使用的 Redis 主机。只有集群和 sentinel 模式才会考虑多个元素。 提供的 URI 使用以下架构 环境变量: 显示更多 |
URI 列表 |
|
主机提供程序 bean 名称。 它是主机提供程序 bean 的 当 环境变量: 显示更多 |
字符串 |
|
|
||
Redis 客户端类型。接受的值为: 环境变量: 显示更多 |
|
|
字符串 |
|
|
角色名称(仅在 Sentinel 模式下考虑)。接受的值为: 环境变量: 显示更多 |
|
|
是否使用副本节点(仅在集群模式和复制模式下考虑)。接受的值为: 环境变量: 显示更多 |
|
|
字符串 |
||
整数 |
|
|
整数 |
|
|
指示连接池清理器应多久执行一次的持续时间。 环境变量: 显示更多 |
|
|
|
||
设置客户端愿意排队的处理程序数量。 客户端将始终以流水线模式工作,这意味着消息可以开始排队。 使用此配置选项,您可以控制您愿意接受多少积压。 环境变量: 显示更多 |
整数 |
|
调整 Redis 响应中允许的嵌套数组数量。 这会影响解析器性能。 环境变量: 显示更多 |
整数 |
|
首次尝试时无法建立池连接时的重新连接尝试次数。 环境变量: 显示更多 |
整数 |
|
首次尝试时无法建立池连接时,重新连接尝试之间的间隔。 环境变量: 显示更多 |
|
|
客户端是否应在连接握手期间执行 环境变量: 显示更多 |
布尔值 |
|
协议协商期间要使用的首选协议版本。 如果未设置,则默认为 RESP 3。 如果禁用协议协商,则此设置无效。 环境变量: 显示更多 |
|
|
哈希槽缓存的 TTL。 集群 Redis 客户端使用哈希槽缓存,以防止不断向第一个静态配置的集群节点发送 此设置仅在集群 Redis 客户端的情况下才有意义,否则无效。 环境变量: 显示更多 |
|
|
是否启用自动故障转移。 这仅对角色为 如果启用,sentinel 客户端将额外创建一个与一个 sentinel 节点的连接,并监视故障转移事件。当选出新的主服务器时,所有与旧主服务器的连接都会自动关闭,并创建与新主服务器的新连接。自动故障转移对于执行常规命令的连接有意义,但对于用于订阅 Redis pub/sub 通道的连接没有意义。 请注意,在旧主服务器发生故障和新主服务器被选出之间有一个短暂的时间段,在此期间现有连接将暂时失败所有操作。在新主服务器被选出后,连接将自动故障转移并再次开始工作。 环境变量: 显示更多 |
布尔值 |
|
如何获取 Redis 拓扑。 默认情况下,拓扑是自动发现的。 这是集群和哨兵客户端的唯一模式。 对于复制客户端,可以将拓扑设置为静态。 如果复制 Redis 客户端的拓扑是静态的,则列表中的第一个节点被认为是主节点,列表中的其余节点被认为是副本。 环境变量: 显示更多 |
|
|
用于标识连接的客户端名称。 如果启用了 如果启用了 环境变量: 显示更多 |
字符串 |
|
是否应在与 Redis 连接时设置客户端名称。 这是必要的,因为 Redis 仅在 6+ 版本中接受 此属性可以与 环境变量: 显示更多 |
布尔值 |
|
要使用的 TLS 配置的名称。 如果配置了名称,它将使用来自 如果未设置 TLS 配置名称,则将使用 默认情况下,不使用默认 TLS 配置。 环境变量: 显示更多 |
字符串 |
|
允许将数据预加载到 Redis 服务器中的文件列表。该文件的格式如下
环境变量: 显示更多 |
字符串列表 |
|
使用 环境变量: 显示更多 |
布尔值 |
|
使用 环境变量: 显示更多 |
布尔值 |
|
连接到 Redis 服务器时要使用的 Redis 主机。只有集群和 sentinel 模式才会考虑多个元素。 提供的 URI 使用以下架构 环境变量: 显示更多 |
URI 列表 |
|
主机提供程序 bean 名称。 它是主机提供程序 bean 的 当 环境变量: 显示更多 |
字符串 |
|
阻塞命令等待 Redis 服务器超时的最大延迟 环境变量: 显示更多 |
|
|
Redis 客户端类型。接受的值为: 环境变量: 显示更多 |
|
|
主服务器名称(仅在 Sentinel 模式下考虑)。 环境变量: 显示更多 |
字符串 |
|
角色名称(仅在 Sentinel 模式下考虑)。接受的值为: 环境变量: 显示更多 |
|
|
是否使用副本节点(仅在集群模式和复制模式下考虑)。接受的值为: 环境变量: 显示更多 |
|
|
Redis 连接的默认密码。 如果未设置,它将尝试从 环境变量: 显示更多 |
字符串 |
|
连接池的最大大小。 环境变量: 显示更多 |
整数 |
|
从池中获取连接的最大等待请求数。 环境变量: 显示更多 |
整数 |
|
指示连接池清理器应多久执行一次的持续时间。 环境变量: 显示更多 |
|
|
未使用的连接回收的超时时间。 环境变量: 显示更多 |
|
|
设置客户端愿意排队的处理程序数量。 客户端将始终以流水线模式工作,这意味着消息可以开始排队。 使用此配置选项,您可以控制您愿意接受多少积压。 环境变量: 显示更多 |
整数 |
|
调整 Redis 响应中允许的嵌套数组数量。 这会影响解析器性能。 环境变量: 显示更多 |
整数 |
|
首次尝试时无法建立池连接时的重新连接尝试次数。 环境变量: 显示更多 |
整数 |
|
首次尝试时无法建立池连接时,重新连接尝试之间的间隔。 环境变量: 显示更多 |
|
|
客户端是否应在连接握手期间执行 环境变量: 显示更多 |
布尔值 |
|
协议协商期间要使用的首选协议版本。 如果未设置,则默认为 RESP 3。 如果禁用协议协商,则此设置无效。 环境变量: 显示更多 |
|
|
哈希槽缓存的 TTL。 集群 Redis 客户端使用哈希槽缓存,以防止不断向第一个静态配置的集群节点发送 此设置仅在集群 Redis 客户端的情况下才有意义,否则无效。 环境变量: 显示更多 |
|
|
是否启用自动故障转移。 这仅对角色为 如果启用,sentinel 客户端将额外创建一个与一个 sentinel 节点的连接,并监视故障转移事件。当选出新的主服务器时,所有与旧主服务器的连接都会自动关闭,并创建与新主服务器的新连接。自动故障转移对于执行常规命令的连接有意义,但对于用于订阅 Redis pub/sub 通道的连接没有意义。 请注意,在旧主服务器发生故障和新主服务器被选出之间有一个短暂的时间段,在此期间现有连接将暂时失败所有操作。在新主服务器被选出后,连接将自动故障转移并再次开始工作。 环境变量: 显示更多 |
布尔值 |
|
如何获取 Redis 拓扑。 默认情况下,拓扑是自动发现的。 这是集群和哨兵客户端的唯一模式。 对于复制客户端,可以将拓扑设置为静态。 如果复制 Redis 客户端的拓扑是静态的,则列表中的第一个节点被认为是主节点,列表中的其余节点被认为是副本。 环境变量: 显示更多 |
|
|
用于标识连接的客户端名称。 如果启用了 如果启用了 环境变量: 显示更多 |
字符串 |
|
是否应在与 Redis 连接时设置客户端名称。 这是必要的,因为 Redis 仅在 6+ 版本中接受 此属性可以与 环境变量: 显示更多 |
布尔值 |
|
要使用的 TLS 配置的名称。 如果配置了名称,它将使用来自 如果未设置 TLS 配置名称,则将使用 默认情况下,不使用默认 TLS 配置。 环境变量: 显示更多 |
字符串 |
|
类型 |
默认 |
|
开发服务是否已被显式启用或禁用。通常默认启用开发服务,除非存在现有配置。 当启用开发服务时,Quarkus 将尝试在开发或测试模式下运行并且 Docker 正在运行时自动配置和启动数据库。 环境变量: 显示更多 |
布尔值 |
|
用于基于容器的 DevServices 提供程序的容器镜像名称。 如果要使用 Redis Stack 模块(bloom、graph、search…),请使用: 环境变量: 显示更多 |
字符串 |
|
开发服务将侦听的可选固定端口。 如果未定义,将随机选择端口。 环境变量: 显示更多 |
整数 |
|
指示由 Quarkus Dev Services 管理的 Redis 服务器是否共享。 共享时,Quarkus 会使用基于标签的服务发现来查找正在运行的容器。 如果找到匹配的容器,则使用该容器,因此不会启动第二个容器。 否则,Redis 的 Dev Services 将启动一个新容器。 发现使用 容器共享仅在开发模式下使用。 环境变量: 显示更多 |
布尔值 |
|
附加到启动的容器的 当您需要多个共享 Redis 服务器时,将使用此属性。 环境变量: 显示更多 |
字符串 |
|
传递给容器的环境变量。 环境变量: 显示更多 |
Map<String,String> |
|
类型 |
默认 |
|
开发服务是否已被显式启用或禁用。通常默认启用开发服务,除非存在现有配置。 当启用开发服务时,Quarkus 将尝试在开发或测试模式下运行并且 Docker 正在运行时自动配置和启动数据库。 环境变量: 显示更多 |
布尔值 |
|
用于基于容器的 DevServices 提供程序的容器镜像名称。 如果要使用 Redis Stack 模块(bloom、graph、search…),请使用: 环境变量: 显示更多 |
字符串 |
|
开发服务将侦听的可选固定端口。 如果未定义,将随机选择端口。 环境变量: 显示更多 |
整数 |
|
指示由 Quarkus Dev Services 管理的 Redis 服务器是否共享。 共享时,Quarkus 会使用基于标签的服务发现来查找正在运行的容器。 如果找到匹配的容器,则使用该容器,因此不会启动第二个容器。 否则,Redis 的 Dev Services 将启动一个新容器。 发现使用 容器共享仅在开发模式下使用。 环境变量: 显示更多 |
布尔值 |
|
附加到启动的容器的 当您需要多个共享 Redis 服务器时,将使用此属性。 环境变量: 显示更多 |
字符串 |
|
传递给容器的环境变量。 环境变量: 显示更多 |
Map<String,String> |
|
类型 |
默认 |
|
布尔值 |
||
设置在 环境变量: 显示更多 |
字符串列表 |
|
设置启用的 SSL/TLS 协议列表。 环境变量: 显示更多 |
字符串列表 |
|
设置当客户端配置为使用代理时,不通过代理的远程主机列表。 环境变量: 显示更多 |
字符串列表 |
|
设置代理用户名。 环境变量: 显示更多 |
字符串 |
|
设置代理密码。 环境变量: 显示更多 |
字符串 |
|
设置代理端口。 默认为 3128。 环境变量: 显示更多 |
整数 |
|
字符串 |
||
设置代理类型。 接受的值为: 环境变量: 显示更多 |
|
|
设置 TCP 接收缓冲区大小。 环境变量: 显示更多 |
整数 |
|
整数 |
||
布尔值 |
||
布尔值 |
||
整数 |
||
布尔值 |
||
启用 环境变量: 显示更多 |
布尔值 |
|
布尔值 |
||
布尔值 |
||
启用 环境变量: 显示更多 |
布尔值 |
|
整数 |
||
设置要绑定到网络连接的本地接口。 当本地地址为空时,它将选择任何本地地址,默认本地地址为空。 环境变量: 显示更多 |
字符串 |
|
类型 |
默认 |
|
布尔值 |
|
|
布尔值 |
|
|
默认情况下禁用 PEM 信任配置。 环境变量: 显示更多 |
布尔值 |
|
信任证书文件(Pem 格式)的逗号分隔列表。 环境变量: 显示更多 |
字符串列表 |
|
默认情况下禁用 JKS 配置。 环境变量: 显示更多 |
布尔值 |
|
密钥文件(JKS 格式)的路径。 环境变量: 显示更多 |
字符串 |
|
密钥文件的密码。 环境变量: 显示更多 |
字符串 |
|
默认情况下禁用 PFX 配置。 环境变量: 显示更多 |
布尔值 |
|
密钥文件(PFX 格式)的路径。 环境变量: 显示更多 |
字符串 |
|
密钥的密码。 环境变量: 显示更多 |
字符串 |
|
默认情况下禁用 PEM 密钥/证书配置。 环境变量: 显示更多 |
布尔值 |
|
密钥文件(Pem 格式)路径的逗号分隔列表。 环境变量: 显示更多 |
字符串列表 |
|
证书文件(Pem 格式)路径的逗号分隔列表。 环境变量: 显示更多 |
字符串列表 |
|
默认情况下禁用 JKS 配置。 环境变量: 显示更多 |
布尔值 |
|
密钥文件(JKS 格式)的路径。 环境变量: 显示更多 |
字符串 |
|
密钥文件的密码。 环境变量: 显示更多 |
字符串 |
|
默认情况下禁用 PFX 配置。 环境变量: 显示更多 |
布尔值 |
|
密钥文件(PFX 格式)的路径。 环境变量: 显示更多 |
字符串 |
|
密钥的密码。 环境变量: 显示更多 |
字符串 |
|
如果应检查服务器的身份,则要使用的主机名验证算法。 应为 如果设置为 环境变量: 显示更多 |
字符串 |
|
类型 |
默认 |
|
设置 ALPN 使用情况。 环境变量: 显示更多 |
布尔值 |
|
设置在 环境变量: 显示更多 |
字符串列表 |
|
设置启用的 SSL/TLS 协议列表。 环境变量: 显示更多 |
字符串列表 |
|
设置空闲超时。 环境变量: 显示更多 |
||
设置连接超时。 环境变量: 显示更多 |
||
设置当客户端配置为使用代理时,不通过代理的远程主机列表。 环境变量: 显示更多 |
字符串列表 |
|
设置代理用户名。 环境变量: 显示更多 |
字符串 |
|
设置代理密码。 环境变量: 显示更多 |
字符串 |
|
设置代理端口。 默认为 3128。 环境变量: 显示更多 |
整数 |
|
设置代理主机。 环境变量: 显示更多 |
字符串 |
|
设置代理类型。 接受的值为: 环境变量: 显示更多 |
|
|
设置读取空闲超时。 环境变量: 显示更多 |
||
设置 TCP 接收缓冲区大小。 环境变量: 显示更多 |
整数 |
|
设置重新连接尝试的值。 环境变量: 显示更多 |
整数 |
|
设置重新连接间隔。 环境变量: 显示更多 |
||
是否重用地址。 环境变量: 显示更多 |
布尔值 |
|
是否重用端口。 环境变量: 显示更多 |
布尔值 |
|
设置 TCP 发送缓冲区大小。 环境变量: 显示更多 |
整数 |
|
设置 环境变量: 显示更多 |
||
启用 环境变量: 显示更多 |
布尔值 |
|
启用 环境变量: 显示更多 |
布尔值 |
|
设置是否启用保持活动 环境变量: 显示更多 |
布尔值 |
|
设置是否启用无延迟 环境变量: 显示更多 |
布尔值 |
|
启用 环境变量: 显示更多 |
布尔值 |
|
设置流量等级的值。 环境变量: 显示更多 |
整数 |
|
设置写入空闲超时。 环境变量: 显示更多 |
||
设置要绑定到网络连接的本地接口。 当本地地址为空时,它将选择任何本地地址,默认本地地址为空。 环境变量: 显示更多 |
字符串 |
|
类型 |
默认 |
|
是否启用 SSL/TLS。 环境变量: 显示更多 |
布尔值 |
|
启用信任所有证书。 默认情况下禁用。 环境变量: 显示更多 |
布尔值 |
|
默认情况下禁用 PEM 信任配置。 环境变量: 显示更多 |
布尔值 |
|
信任证书文件(Pem 格式)的逗号分隔列表。 环境变量: 显示更多 |
字符串列表 |
|
默认情况下禁用 JKS 配置。 环境变量: 显示更多 |
布尔值 |
|
密钥文件(JKS 格式)的路径。 环境变量: 显示更多 |
字符串 |
|
密钥文件的密码。 环境变量: 显示更多 |
字符串 |
|
默认情况下禁用 PFX 配置。 环境变量: 显示更多 |
布尔值 |
|
密钥文件(PFX 格式)的路径。 环境变量: 显示更多 |
字符串 |
|
密钥的密码。 环境变量: 显示更多 |
字符串 |
|
默认情况下禁用 PEM 密钥/证书配置。 环境变量: 显示更多 |
布尔值 |
|
密钥文件(Pem 格式)路径的逗号分隔列表。 环境变量: 显示更多 |
字符串列表 |
|
证书文件(Pem 格式)路径的逗号分隔列表。 环境变量: 显示更多 |
字符串列表 |
|
默认情况下禁用 JKS 配置。 环境变量: 显示更多 |
布尔值 |
|
密钥文件(JKS 格式)的路径。 环境变量: 显示更多 |
字符串 |
|
密钥文件的密码。 环境变量: 显示更多 |
字符串 |
|
默认情况下禁用 PFX 配置。 环境变量: 显示更多 |
布尔值 |
|
密钥文件(PFX 格式)的路径。 环境变量: 显示更多 |
字符串 |
|
密钥的密码。 环境变量: 显示更多 |
字符串 |
|
如果应检查服务器的身份,则要使用的主机名验证算法。 应为 如果设置为 环境变量: 显示更多 |
字符串 |
|
关于 Duration 格式
要写入持续时间值,请使用标准 您还可以使用简化的格式,以数字开头
在其他情况下,简化格式将被转换为
|