Jedis 指南

Jedis 指南

Jedis 指南

将 Java 应用程序连接到 Redis 数据库

安装 Redis 和 Redis 客户端,然后将 Java 应用程序连接到 Redis 数据库。

Jedis

Jedis 是一款为 Redis 设计的 Java 客户端,以性能和易用性为目标。

安装

要将 Jedis 作为依赖项包含在应用程序中,请按如下方式编辑依赖项文件。

如果您使用 Maven

redis.clients

jedis

5.1.2

如果您使用 Gradle

repositories {

mavenCentral()

}

//...

dependencies {

implementation 'redis.clients:jedis:5.1.2'

//...

}

如果您使用 JAR 文件,请从 Maven Central 或任何其他 Maven 存储库下载最新的 Jedis 和 Apache Commons Pool2 JAR 文件。

从 源代码 构建

连接

对于许多应用程序,最好使用连接池。您可以像这样实例化和使用 Jedis 连接池

package org.example;

import redis.clients.jedis.Jedis;

import redis.clients.jedis.JedisPool;

public class Main {

public static void main(String[] args) {

JedisPool pool = new JedisPool("localhost", 6379);

try (Jedis jedis = pool.getResource()) {

// Store & Retrieve a simple string

jedis.set("foo", "bar");

System.out.println(jedis.get("foo")); // prints bar

// Store & Retrieve a HashMap

Map hash = new HashMap<>();;

hash.put("name", "John");

hash.put("surname", "Smith");

hash.put("company", "Redis");

hash.put("age", "29");

jedis.hset("user-session:123", hash);

System.out.println(jedis.hgetAll("user-session:123"));

// Prints: {name=John, surname=Smith, company=Redis, age=29}

}

}

}

由于为每个命令添加 try-with-resources 块可能会很麻烦,因此可以考虑使用 JedisPooled 作为一种更简单的连接池方式。

import redis.clients.jedis.JedisPooled;

//...

JedisPooled jedis = new JedisPooled("localhost", 6379);

jedis.set("foo", "bar");

System.out.println(jedis.get("foo")); // prints "bar"

连接到 Redis 集群

要连接到 Redis 集群,请使用 JedisCluster。

import redis.clients.jedis.JedisCluster;

import redis.clients.jedis.HostAndPort;

//...

Set jedisClusterNodes = new HashSet();

jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7379));

jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7380));

JedisCluster jedis = new JedisCluster(jedisClusterNodes);

使用 TLS 连接到生产 Redis

部署应用程序时,请使用 TLS 并遵循 Redis 安全 指南。

在将应用程序连接到启用了 TLS 的 Redis 服务器之前,请确保证书和私钥采用正确的格式。

要将用户证书和私钥从 PEM 格式转换为 pkcs12,请使用此命令

openssl pkcs12 -export -in ./redis_user.crt -inkey ./redis_user_private.key -out redis-user-keystore.p12 -name "redis"

输入密码以保护您的 pkcs12 文件。

使用 JDK 附带的 keytool 将服务器(CA)证书转换为 JKS 格式。

keytool -importcert -keystore truststore.jks \

-storepass REPLACE_WITH_YOUR_PASSWORD \

-file redis_ca.pem

使用此代码段与 Redis 数据库建立安全连接。

package org.example;

import redis.clients.jedis.*;

import javax.net.ssl.*;

import java.io.FileInputStream;

import java.io.IOException;

import java.security.GeneralSecurityException;

import java.security.KeyStore;

public class Main {

public static void main(String[] args) throws GeneralSecurityException, IOException {

HostAndPort address = new HostAndPort("my-redis-instance.cloud.redislabs.com", 6379);

SSLSocketFactory sslFactory = createSslSocketFactory(

"./truststore.jks",

"secret!", // use the password you specified for keytool command

"./redis-user-keystore.p12",

"secret!" // use the password you specified for openssl command

);

JedisClientConfig config = DefaultJedisClientConfig.builder()

.ssl(true).sslSocketFactory(sslFactory)

.user("default") // use your Redis user. More info https://redis.ac.cn/docs/management/security/acl/

.password("secret!") // use your Redis password

.build();

JedisPooled jedis = new JedisPooled(address, config);

jedis.set("foo", "bar");

System.out.println(jedis.get("foo")); // prints bar

}

private static SSLSocketFactory createSslSocketFactory(

String caCertPath, String caCertPassword, String userCertPath, String userCertPassword)

throws IOException, GeneralSecurityException {

KeyStore keyStore = KeyStore.getInstance("pkcs12");

keyStore.load(new FileInputStream(userCertPath), userCertPassword.toCharArray());

KeyStore trustStore = KeyStore.getInstance("jks");

trustStore.load(new FileInputStream(caCertPath), caCertPassword.toCharArray());

TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509");

trustManagerFactory.init(trustStore);

KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("PKIX");

keyManagerFactory.init(keyStore, userCertPassword.toCharArray());

SSLContext sslContext = SSLContext.getInstance("TLS");

sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);

return sslContext.getSocketFactory();

}

}

生产使用

配置连接池

如前一节所述,使用 JedisPool 或 JedisPooled 创建连接池。在 Jedis 4.0.0 版本中添加的 JedisPooled 提供了与 JedisPool 类似的功能,但 API 更加直接。连接池保存指定数量的连接,在需要时创建更多连接,并在不再需要时终止它们。

以下是池中简化的连接生命周期

从池中请求连接。

提供连接

当有非活动连接可用时,提供空闲连接,或

当连接数低于 maxTotal 时,创建新连接。

连接变为活动状态。

将连接释放回池中。

连接标记为陈旧。

连接保持空闲 minEvictableIdleTime。

如果连接数大于 minIdle,连接变为可驱逐。

连接准备关闭。

正确配置连接池非常重要。使用 Apache Commons Pool2 中的 GenericObjectPoolConfig。

ConnectionPoolConfig poolConfig = new ConnectionPoolConfig();

// maximum active connections in the pool,

// tune this according to your needs and application type

// default is 8

poolConfig.setMaxTotal(8);

// maximum idle connections in the pool, default is 8

poolConfig.setMaxIdle(8);

// minimum idle connections in the pool, default 0

poolConfig.setMinIdle(0);

// Enables waiting for a connection to become available.

poolConfig.setBlockWhenExhausted(true);

// The maximum number of seconds to wait for a connection to become available

poolConfig.setMaxWait(Duration.ofSeconds(1));

// Enables sending a PING command periodically while the connection is idle.

poolConfig.setTestWhileIdle(true);

// controls the period between checks for idle connections in the pool

poolConfig.setTimeBetweenEvictionRuns(Duration.ofSeconds(1));

// JedisPooled does all hard work on fetching and releasing connection to the pool

// to prevent connection starvation

JedisPooled jedis = new JedisPooled(poolConfig, "localhost", 6379);

超时

要为连接设置超时,请使用带 timeout 参数的 JedisPooled 或 JedisPool 构造函数,或使用带 socketTimeout 和 connectionTimeout 参数的 JedisClientConfig

HostAndPort hostAndPort = new HostAndPort("localhost", 6379);

JedisPooled jedisWithTimeout = new JedisPooled(hostAndPort,

DefaultJedisClientConfig.builder()

.socketTimeoutMillis(5000) // set timeout to 5 seconds

.connectionTimeoutMillis(5000) // set connection timeout to 5 seconds

.build(),

poolConfig

);

异常处理

Jedis 异常层次结构根植于 JedisException,后者实现了 RuntimeException,因此都是未检查异常。

JedisException

├── JedisDataException

│ ├── JedisRedirectionException

│ │ ├── JedisMovedDataException

│ │ └── JedisAskDataException

│ ├── AbortedTransactionException

│ ├── JedisAccessControlException

│ └── JedisNoScriptException

├── JedisClusterException

│ ├── JedisClusterOperationException

│ ├── JedisConnectionException

│ └── JedisValidationException

└── InvalidURIException

一般异常

通常,Jedis 在执行命令时可能会抛出以下异常

JedisConnectionException - 当与 Redis 的连接意外丢失或关闭时。使用 Resilience4J 和内置的 Jedis 故障转移机制配置故障转移以自动处理此异常。

JedisAccessControlException - 当用户没有执行命令的权限或用户 ID 和/或密码不正确时。

JedisDataException - 当发送到 Redis 服务器或从 Redis 服务器接收的数据有问题时。通常,错误消息将包含有关失败命令的更多信息。

JedisException - 此异常是一个 catch-all 异常,可以针对任何其他意外错误抛出。

可以抛出 JedisException 的条件

使用 PING 命令进行健康检查时返回不良

关闭期间发生故障

发出命令(断开连接)时 Pub/Sub 发生故障

任何未知的服务器消息

Sentinel:可以连接到 Sentinel,但未监控主服务器或所有 Sentinel 都已关闭。

MULTI 或 DISCARD 命令失败

分片命令键哈希检查失败或没有可访问的分片

重试截止时间已过/尝试次数(重试命令执行器)

POOL - 池已耗尽,添加空闲对象时出错,将损坏的资源返回池

所有 Jedis 异常都是运行时异常,并且在大多数情况下无法恢复,因此通常会冒泡到捕获错误消息的 API。

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");

了解更多

Jedis API 参考

使用 Jedis 进行故障转移

GitHub

对本页进行评分

提交

相关文章

返利app的排行
365在线体育

返利app的排行

⌛ 06-30 👁️‍🗨️ 1088
梦幻新区什么时候能抓须弥?(梦幻西游新区一般多久出须弥)
bte365正规网站

梦幻新区什么时候能抓须弥?(梦幻西游新区一般多久出须弥)

⌛ 08-13 👁️‍🗨️ 9304
墨西哥世界杯
bte365正规网站

墨西哥世界杯

⌛ 10-15 👁️‍🗨️ 7968
WELLA威娜
365bet网上手机投注

WELLA威娜

⌛ 10-06 👁️‍🗨️ 4534
[交流]询价:五技能蓝书变异吸血鬼价格
365在线体育

[交流]询价:五技能蓝书变异吸血鬼价格

⌛ 08-28 👁️‍🗨️ 4307
电器开关股票2024第三季度毛利润10大排行榜(附榜单)
365在线体育

电器开关股票2024第三季度毛利润10大排行榜(附榜单)

⌛ 10-24 👁️‍🗨️ 1865