redis集群搭建与java客户端连接的核心在于部署多实例并使用适配的客户端库。1. 首先创建多个redis实例目录,配置redis.conf文件启用集群模式、设置端口、日志路径、数据目录等;2. 启动所有实例后使用redis-cli工具创建集群(至少6个节点,3主3从);3. 使用jedis或lettuce作为java客户端,添加maven依赖并通过jediscluster类连接集群,只需提供部分节点信息即可自动发现整个集群拓扑。常见问题包括网络与防火墙配置需开放port和port+10000端口、ip绑定应根据环境选择具体ip或0.0.0.0、nodes.conf文件不可复制避免冲突、确保至少3主节点以支持故障转移、开启持久化防止数据丢失、保持节点时间同步。java客户端通过cluster slots命令获取集群结构,并在遇到moved/ask重定向时自动更新映射关系;合理配置连接池可优化性能;故障转移由集群内部机制处理,客户端会自动感知新主节点。相比主从模式(单点故障、无法扩展)、哨兵模式(仅实现自动故障转移、写入仍受限),集群模式具备高可用性和水平扩展能力,适用于大规模高并发场景。

Redis集群的搭建与Java客户端的连接,核心在于理解Redis分布式存储的机制,并选择合适的客户端库进行适配。简单来说,你需要部署多台Redis实例,将它们组织成一个高可用、可扩展的集群,然后通过Java客户端(比如Jedis或Lettuce)来感知并操作这个集群。这听起来可能有些复杂,但实际上,只要掌握了关键步骤和一些常见“坑”,整个过程会顺利很多。

要搭建Redis集群并用Java客户端连接,我们可以分两步走。
第一步:搭建Redis集群
立即学习“Java免费学习笔记(深入)”;

我通常会在多台机器(或虚拟机,甚至单机多端口模拟)上进行。这里以最常见的单机多端口模拟为例,实际生产环境请部署在不同物理机上。
准备实例目录和配置文件:
为每个Redis实例创建独立的目录,例如:redis-cluster/7000, redis-cluster/7001, redis-cluster/7002, redis-cluster/7003, redis-cluster/7004, redis-cluster/7005。
每个目录下放置一份 redis.conf 文件,并进行以下关键配置:

# 端口号,每个实例不同 port 7000 # 启用集群模式 cluster-enabled yes # 集群配置文件,每个实例独立 cluster-config-file nodes-7000.conf # 节点超时时间 cluster-node-timeout 5000 # AOF持久化,建议开启 appendonly yes # 后台运行 daemonize yes # 日志文件路径 logfile "7000.log" # 数据目录 dir "/path/to/redis-cluster/7000" # 绑定IP,如果是多机部署,这里要填实际IP,不能是127.0.0.1 # 如果是单机测试,可以留127.0.0.1,但如果Java客户端在外部,则需绑定0.0.0.0或具体IP bind 0.0.0.0 # 保护模式,生产环境建议关闭或者配置密码 protected-mode no
依此类推,为7001到7005端口的实例修改对应的 port、cluster-config-file 和 dir。
启动所有Redis实例:
进入每个实例的目录,执行:
redis-server redis.conf
确认所有实例都已启动并监听对应端口。
创建Redis集群:
当所有实例都启动后,使用 redis-cli 工具创建集群。我通常会选择至少6个实例,3主3从,这样可以保证高可用性。
redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 --cluster-replicas 1
--cluster-replicas 1 表示每个主节点会有一个从节点。执行命令后,它会提示你如何分配哈希槽和主从关系,输入 yes 确认即可。
验证集群状态:redis-cli -c -p 7000 cluster inforedis-cli -c -p 7000 cluster nodes
确保集群状态正常,所有节点都已连接,且主从关系正确。
第二步:Java客户端连接Redis集群
我个人比较常用Jedis,因为它上手快,社区支持也很好。Lettuce也是一个不错的选择,尤其在响应式编程方面。
添加Maven依赖(以Jedis为例):
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.6.0</version> <!-- 使用最新稳定版本 -->
</dependency>编写Java代码连接集群:
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;
import java.util.HashSet;
import java.util.Set;
public class RedisClusterClient {
public static void main(String[] args) {
Set<HostAndPort> jedisClusterNodes = new HashSet<>();
// 只需要提供部分集群节点信息,JedisCluster会自动发现其他节点
jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7000));
jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7001));
jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7002));
// 配置连接池,生产环境非常重要
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(100); // 最大连接数
poolConfig.setMaxIdle(20); // 最大空闲连接数
poolConfig.setMinIdle(5); // 最小空闲连接数
poolConfig.setTestOnBorrow(true); // 借用连接时是否测试
poolConfig.setTestOnReturn(true); // 归还连接时是否测试
poolConfig.setTestWhileIdle(true); // 空闲时是否测试
JedisCluster jc = null;
try {
// 构造JedisCluster实例,传入节点信息和连接池配置
// timeout参数是连接超时和读写超时,单位毫秒
jc = new JedisCluster(jedisClusterNodes, 2000, 2000, 5, "your_password_if_any", poolConfig);
// 进行一些操作
jc.set("mykey", "Hello Redis Cluster!");
String value = jc.get("mykey");
System.out.println("Get 'mykey': " + value);
jc.set("anotherkey", "This is distributed!");
System.out.println("Get 'anotherkey': " + jc.get("anotherkey"));
// 测试不同哈希槽的key
jc.set("{user}:1001", "User A Data");
jc.set("{user}:1002", "User B Data"); // 这两个key会因为哈希标签在同一个槽位
System.out.println("Get '{user}:1001': " + jc.get("{user}:1001"));
System.out.println("Get '{user}:1002': " + jc.get("{user}:1002"));
} catch (Exception e) {
System.err.println("Error connecting to Redis Cluster: " + e.getMessage());
e.printStackTrace();
} finally {
if (jc != null) {
try {
jc.close(); // 关闭连接,将连接返回连接池
} catch (Exception e) {
System.err.println("Error closing JedisCluster: " + e.getMessage());
}
}
}
}
}请注意,JedisCluster 的构造函数只需要提供集群中任意几个可达的节点即可,它会自动发现整个集群的拓扑结构。这很方便,你不需要列出所有节点。
在实际操作Redis集群时,我遇到过不少让人头疼的问题,这里我总结了一些比较常见的“坑”和它们的解决思路。
1. 网络与防火墙:
这是最常见的,也是最容易被忽视的问题。Redis集群节点之间需要互相通信,不仅需要开放你配置的 port (例如 6379),还需要开放 port + 10000 的端口 (例如 16379) 用于集群总线通信。如果你的服务器有防火墙(如firewalld、ufw或云服务商的安全组),请务必放行这两个端口范围。我曾有一次因为云服务器安全组没开全,导致集群一直无法正常握手,排查了半天。
2. IP绑定与NAT问题:
在 redis.conf 中,bind 参数至关重要。
bind 127.0.0.1 通常没问题。bind 127.0.0.1 就会导致外部无法连接。你应该绑定服务器的实际IP地址,或者直接 bind 0.0.0.0 (允许所有IP连接,生产环境慎用,或配合防火墙)。cluster-announce-ip 和 cluster-announce-port 参数来告诉其他节点或客户端,自己对外应该如何被访问。这个就比较高级了,但一旦遇到,会让你抓狂。3. nodes.conf 文件问题:
每个Redis集群节点都有一个 nodes.conf 文件,它记录了集群的拓扑结构、节点ID、IP、端口等信息。
nodes.conf 文件。每个节点启动时,如果这个文件不存在,它会生成一个新的节点ID并创建文件;如果存在,它会尝试根据文件内容加入集群。如果你复制了,可能会导致节点ID冲突或集群状态混乱。nodes.conf 文件,然后重新启动并创建集群。4. 节点数量不足: Redis集群至少需要3个主节点才能正常工作(因为集群需要大多数主节点同意才能进行故障转移)。如果你只有1个或2个主节点,集群将无法创建或在节点故障时无法提供高可用性。建议至少部署3主3从共6个节点。
5. 持久化与数据丢失:
虽然集群提供了高可用性,但如果节点都宕机且没有持久化,数据还是会丢失。务必开启 appendonly yes (AOF) 或配置RDB快照,并定期备份。在集群环境中,数据分散在不同节点,单个节点的持久化配置对整个集群的健壮性至关重要。
6. 时间同步: 所有Redis集群节点的时间必须保持同步,否则可能导致集群内部对节点状态的判断出现偏差,影响故障转移的准确性。使用NTP服务同步时间是一个好习惯。
Java客户端在连接Redis集群和处理故障转移方面,其实做得相当智能,这大大减轻了我们开发者的负担。
1. 客户端如何发现所有节点?
像JedisCluster这样的客户端,你只需要在初始化时提供集群中任意几个(通常是3-5个就足够了)可达的节点信息。客户端拿到这些“种子”节点后,会通过这些节点去执行 CLUSTER SLOTS 命令。这个命令会返回整个集群的哈希槽分布情况,以及每个哈希槽由哪个主节点负责,其从节点又是谁。客户端拿到这个完整的集群拓扑图后,就会在内部维护一个最新的映射关系:哪个哈希槽对应哪个主节点。当集群拓扑发生变化(比如节点下线、上线、主从切换、槽位迁移),客户端会定期或在遇到MOVED/ASK重定向时更新这个拓扑图。
2. 连接池的重要性: 无论是连接单机Redis还是集群,连接池都是性能优化的关键。每次创建TCP连接和进行身份验证都是有开销的。
JedisPoolConfig 允许你配置连接池的最大连接数、最大空闲连接数、最小空闲连接数、连接测试策略等。setMaxTotal (最大连接数): 控制同时活跃的连接总数。设置得太小可能导致请求等待,设置得太大可能耗尽服务器资源。setMaxIdle 和 setMinIdle: 决定了连接池中保持空闲连接的数量。保持一定数量的空闲连接可以避免频繁创建和销毁连接的开销。setTestOnBorrow、setTestOnReturn、setTestWhileIdle: 这些测试策略可以确保你从连接池获取到的连接是“活”的,避免使用到已经失效的连接。虽然会带来一些额外开销,但在生产环境中,为了稳定性通常是值得的。我个人建议至少开启 setTestWhileIdle。3. 读写操作与哈希槽重定向: 当Java客户端需要对一个key进行操作时,它会先计算这个key对应的哈希槽(通过CRC16算法),然后根据内部维护的槽位-节点映射关系,将请求发送到负责该槽位的主节点。
MOVED 错误,并告诉客户端新的负责节点地址。客户端收到 MOVED 后,会更新自己的槽位映射,然后将请求重定向到正确的节点。这个过程对应用是透明的。ASK 重定向。这表示槽位正在迁移中,但目标key可能还在源节点上。客户端收到 ASK 后,会先连接到目标节点,发送一个 ASKING 命令,然后再发送实际的命令。这通常是临时的,用于平滑迁移。4. 故障转移处理: Redis集群的故障转移是内置的,客户端对此是感知并适应的。
CLUSTER SLOTS 请求,获取最新的拓扑信息。在Redis的世界里,高可用和可扩展性有几种不同的实现路径:主从复制、哨兵模式,以及我们今天讨论的集群模式。理解它们的区别,能帮助你根据实际业务需求做出最合适的选择。
1. 主从复制模式 (Master-Slave Replication):
2. 哨兵模式 (Sentinel Mode):
以上就是Redis集群搭建与Java客户端连接详细教程的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号