连接到服务器

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

基本连接

以下代码打开与本地Redis服务器的基本连接:

package org.example;
import redis.clients.jedis.UnifiedJedis;

public class Main {
    public static void main(String[] args) {
        UnifiedJedis jedis = new UnifiedJedis("redis://localhost:6379");

        // Code that interacts with Redis...

        jedis.close();
    }
}

连接后,您可以通过存储和检索一个简单的字符串值来检查连接:

...

String res1 = jedis.set("bike:1", "Deimos");
System.out.println(res1); // OK

String res2 = jedis.get("bike:1");
System.out.println(res2); // Deimos

...

连接到Redis集群

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

import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.HostAndPort;

//...

Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>();
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.io/docs/latest/operate/oss_and_stack/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();
    }
}

使用客户端缓存进行连接

客户端缓存是一种减少客户端和服务器之间网络流量的技术,从而提高性能。有关客户端缓存的工作原理以及如何有效使用它的更多信息,请参见客户端缓存介绍

要启用客户端缓存,请指定 RESP3 协议并在连接期间传递缓存配置对象。

下面的示例展示了连接到默认主机和端口localhost:6379的最简单的客户端缓存连接。 上面描述的所有连接变体都接受这些参数,因此您可以以完全相同的方式使用客户端缓存与连接池或集群连接。

注意:
客户端缓存需要Jedis v5.2.0或更高版本。 为了最大化与所有Redis产品的兼容性,客户端缓存 需要Redis v7.4或更高版本支持。
HostAndPort endpoint = new HostAndPort("localhost", 6379);

DefaultJedisClientConfig config = DefaultJedisClientConfig
    .builder()
    .password("secretPassword")
    .protocol(RedisProtocol.RESP3)
    .build();

CacheConfig cacheConfig = CacheConfig.builder().maxSize(1000).build();

UnifiedJedis client = new UnifiedJedis(endpoint, config, cacheConfig);

一旦连接成功,通常的Redis命令将透明地与缓存一起工作:

client.set("city", "New York");
client.get("city");     // Retrieved from Redis server and cached
client.get("city");     // Retrieved from cache

如果你使用redis-cli连接到同一个Redis数据库并运行MONITOR命令,你可以看到缓存的工作情况。如果你运行上面的代码但在连接期间没有传递cacheConfig,你应该在MONITOR的输出中看到以下内容:

1723109720.268903 [...] "SET" "city" "New York"
1723109720.269681 [...] "GET" "city"
1723109720.270205 [...] "GET" "city"

服务器响应所有的get("city")调用。 如果你再次添加cacheConfig运行代码,你将会看到

1723110248.712663 [...] "SET" "city" "New York"
1723110248.713607 [...] "GET" "city"

第一次get("city")调用联系了服务器,但第二次调用由缓存满足。

从缓存中移除项目

你可以使用缓存对象的deleteByRedisKey()方法从缓存中移除单个键。这会移除与每个指定键相关的所有缓存项,因此所有来自多键命令(如MGET)和复合数据结构(如哈希)的结果将立即被清除。下面的示例展示了从缓存中移除单个键的效果:

client.hget("person:1", "name");    // Read from the server
client.hget("person:1", "name");    // Read from the cache

client.hget("person:2", "name");    // Read from the server
client.hget("person:2", "name");    // Read from the cache

Cache myCache = client.getCache();
myCache.deleteByRedisKey("person:1");

client.hget("person:1", "name");    // Read from the server
client.hget("person:1", "name");    // Read from the cache

client.hget("person:2", "name");    // Still read from the cache

你也可以使用flush()方法来清除所有缓存项:

client.hget("person:1", "name");    // Read from the server
client.hget("person:1", "name");    // Read from the cache

client.hget("person:2", "name");    // Read from the server
client.hget("person:2", "name");    // Read from the cache

Cache myCache = client.getCache();
myCache.flush();

client.hget("person:1", "name");    // Read from the server
client.hget("person:1", "name");    // Read from the cache

client.hget("person:2", "name");    // Read from the server
client.hget("person:2", "name");    // Read from the cache

如果任何连接(包括来自连接池的连接)断开,客户端也会自动刷新缓存。

使用连接池进行连接

在生产环境中,您应该使用连接池来管理连接,而不是单独打开和关闭连接。连接池维护多个打开的连接并有效地重用它们。当您从池中打开连接时,池会分配其中一个打开的连接。当您随后关闭相同的连接时,它实际上并没有关闭,而是返回到池中以供重用。这避免了重复连接和断开连接的开销。有关更多信息,请参阅连接池和多路复用

使用以下代码连接连接池:

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<String, String> 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作为连接池的更简单方式。JedisPooled在Jedis 4.0.0版本中添加,提供了与JedisPool类似的功能,但API更为直接。

import redis.clients.jedis.JedisPooled;

//...

JedisPooled jedis = new JedisPooled("localhost", 6379);
jedis.set("foo", "bar");
System.out.println(jedis.get("foo")); // prints "bar"

连接池持有指定数量的连接,在必要时创建更多连接,并在不再需要时终止它们。

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

  1. 从池中请求一个连接。
  2. A connection is served:
    • 当有非活动连接可用时,空闲连接会被服务,或者
    • 当连接数低于maxTotal时,会创建一个新的连接。
  3. 连接变为活动状态。
  4. 连接被释放回池中。
  5. 连接被标记为陈旧。
  6. 连接保持空闲状态的时间为minEvictableIdleTime
  7. 如果连接数大于minIdle,则连接变为可驱逐。
  8. 连接已准备好关闭。

正确配置连接池非常重要。 使用来自Apache Commons Pool2GenericObjectPoolConfig

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);
RATE THIS PAGE
Back to top ↑