实现分布式读写集群 (提升两台服务器的性能,支持分片存储+并行读写), Redis Cluster(Redis集群模式),而非哨兵模式。Redis Cluster会自动将数据分片存储在不同节点,同时支持读写分离和故障转移,完美适配两台服务器的需求。
核心架构说明
- 节点规划 :2台服务器(192.168.0.4/7)各部署2个Redis节点(1主1从),共2主2从的Redis Cluster集群(满足最小集群要求,每个主节点负责一部分哈希槽)。
- 端口映射 :业务仅需访问
8015端口,通过Nginx反向代理+Redis Cluster客户端实现统一入口+分片访问。 - 性能提升:数据分片存储在2个主节点,读写请求分散到不同节点,充分利用两台服务器的资源。
一、服务器规划
| 服务器 | 角色 | 端口(容器内) | 宿主机映射 | 说明 |
|---|---|---|---|---|
| 192.168.0.4 | Redis主节点1 | 6379 | 6379:6379 | 负责哈希槽0-8191 |
| 192.168.0.4 | Redis从节点1(备1) | 6380 | 6380:6379 | 主节点1的副本 |
| 192.168.0.7 | Redis主节点2 | 6379 | 6379:6379 | 负责哈希槽8192-16383 |
| 192.168.0.7 | Redis从节点2(备2) | 6380 | 6380:6379 | 主节点2的副本 |
| 192.168.0.4 | Nginx代理 | 80 | 8015:80 | 业务统一访问8015端口 |
二、配置步骤(服务器A:192.168.0.4)
1. 创建目录结构
bash
mkdir -p /data/redis-cluster/{node1,node2,nginx}
cd /data/redis-cluster
2. 编写docker-compose.yml
yaml
version: '3.8'
services:
# Redis主节点1(192.168.0.4:6379)
redis-node1:
image: redis:7.2-alpine
container_name: redis-node1-4
restart: always
ports:
- "6379:6379"
- "16379:16379" # Cluster总线端口(容器内+10000)
volumes:
- ./node1/data:/data
- ./node1/redis.conf:/etc/redis/redis.conf
command: redis-server /etc/redis/redis.conf
environment:
- TZ=Asia/Shanghai
networks:
- redis-net
sysctls:
- net.core.somaxconn=1024
# Redis从节点1(192.168.0.4:6380)
redis-node2:
image: redis:7.2-alpine
container_name: redis-node2-4
restart: always
ports:
- "6380:6379"
- "16380:16379"
volumes:
- ./node2/data:/data
- ./node2/redis.conf:/etc/redis/redis.conf
command: redis-server /etc/redis/redis.conf
environment:
- TZ=Asia/Shanghai
networks:
- redis-net
depends_on:
- redis-node1
# Nginx代理(统一入口8015)
nginx-proxy:
image: nginx:alpine
container_name: redis-nginx-4
restart: always
ports:
- "8015:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
networks:
- redis-net
networks:
redis-net:
driver: bridge
3. Redis节点配置(node1/redis.conf、node2/redis.conf)
两个节点配置一致(仅端口和节点ID不同,Cluster自动识别):
conf
# 基础配置
bind 0.0.0.0
port 6379
daemonize no
pidfile /var/run/redis.pid
logfile ""
databases 16
dir /data
requirepass "123456" # 密码
masterauth "123456" # 主从同步密码
# Cluster核心配置
cluster-enabled yes # 开启Cluster模式
cluster-config-file nodes.conf # Cluster节点配置文件
cluster-node-timeout 15000 # 节点超时时间
cluster-announce-ip 192.168.0.4 # 暴露宿主机IP
cluster-announce-port 6379 # node1用6379,node2用6380
cluster-announce-bus-port 16379 # node1用16379,node2用16380
# 持久化
appendonly yes
appendfsync everysec
三、配置步骤(服务器B:192.168.0.7)
1. 创建目录结构
bash
mkdir -p /data/redis-cluster/{node1,node2}
cd /data/redis-cluster
2. 编写docker-compose.yml
yaml
version: '3.8'
services:
# Redis主节点2(192.168.0.7:6379)
redis-node1:
image: redis:7.2-alpine
container_name: redis-node1-7
restart: always
ports:
- "6379:6379"
- "16379:16379"
volumes:
- ./node1/data:/data
- ./node1/redis.conf:/etc/redis/redis.conf
command: redis-server /etc/redis/redis.conf
environment:
- TZ=Asia/Shanghai
networks:
- redis-net
sysctls:
- net.core.somaxconn=1024
# Redis从节点2(192.168.0.7:6380)
redis-node2:
image: redis:7.2-alpine
container_name: redis-node2-7
restart: always
ports:
- "6380:6379"
- "16380:16379"
volumes:
- ./node2/data:/data
- ./node2/redis.conf:/etc/redis/redis.conf
command: redis-server /etc/redis/redis.conf
environment:
- TZ=Asia/Shanghai
networks:
- redis-net
depends_on:
- redis-node1
networks:
redis-net:
driver: bridge
3. Redis节点配置(node1/redis.conf、node2/redis.conf)
仅修改cluster-announce-ip为192.168.0.7,其余与服务器A一致:
conf
cluster-announce-ip 192.168.0.7 # 服务器B的IP
cluster-announce-port 6379 # node1用6379,node2用6380
cluster-announce-bus-port 16379 # node1用16379,node2用16380
四、Nginx配置(服务器A:nginx/nginx.conf)
实现8015端口统一代理到Cluster所有主节点:
nginx
worker_processes auto;
events {
worker_connections 1024;
}
stream { # Redis是TCP协议,用stream模块代理
upstream redis-cluster {
server 192.168.0.4:6379; # 主节点1
server 192.168.0.7:6379; # 主节点2
}
server {
listen 80; # 映射到宿主机8015
proxy_pass redis-cluster;
proxy_timeout 30s;
proxy_connect_timeout 5s;
}
}
http {
server {
listen 80;
server_name localhost;
return 403; # 防止HTTP访问
}
}
五、启动并初始化Cluster
1. 启动所有节点
bash
# 服务器A
cd /data/redis-cluster && docker-compose up -d
# 服务器B
cd /data/redis-cluster && docker-compose up -d
这里启动的时候我发现我nginx起不来

经过查看日志排查:

他说我的80端口被占用,这里需要修改容器的80端口
直接修改nginx配置文件和docker-compose文件中对应的nginx,再启动就正常了

2. 初始化Cluster集群
在任意服务器执行(需安装Redis客户端,或进入容器执行):
bash
# 进入服务器A的node1容器
docker exec -it redis-node1-4 redis-cli -a 123456
# 创建Cluster(2主2从,主节点为4:6379和7:6379,从节点为4:6380和7:6380)
127.0.0.1:6379> cluster create 192.168.0.4:6379 192.168.0.7:6379 192.168.0.4:6380 192.168.0.7:6380 --cluster-replicas 1 --cluster-yes
3. 验证Cluster状态
bash
redis-cli -h 192.168.0.4 -p 6379 -a 123456 cluster info
# 输出cluster_state:ok表示集群正常
redis-cli -h 192.168.0.4 -p 6379 -a 123456 cluster nodes
# 查看节点角色和哈希槽分配(主节点分别持有0-8191和8192-16383)
六、业务访问方式
1. 通过8015端口访问(推荐)
业务连接192.168.0.4:8015,使用Redis Cluster客户端(自动分片读写):
Python示例(redis-py-cluster)
python
from rediscluster import RedisCluster
# 配置Cluster节点(通过8015代理)
startup_nodes = [{"host": "192.168.0.4", "port": 8015}]
rc = RedisCluster(
startup_nodes=startup_nodes,
password="123456",
decode_responses=True,
skip_full_coverage_check=True # 跳过全槽位检查(2主节点已覆盖所有槽位)
)
# 测试分片读写
rc.set("key1", "value1") # 自动路由到某主节点
rc.set("key2", "value2")
print(rc.get("key1"))
print(rc.get("key2"))
Java示例(JedisCluster)
java
Set<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("192.168.0.4", 8015));
JedisPoolConfig poolConfig = new JedisPoolConfig();
JedisCluster jedisCluster = new JedisCluster(nodes, Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT, "123456", poolConfig);
jedisCluster.set("key1", "value1");
System.out.println(jedisCluster.get("key1"));
七、核心优势
- 性能提升:数据分片存储在2个主节点,读写请求并行处理,充分利用两台服务器的CPU/内存。
- 高可用:每个主节点有从节点备份,主节点故障时自动提升从节点为主,业务无感。
- 统一入口 :业务仅需访问
8015端口,无需关心集群内部节点。 - 弹性扩展:后续可增加服务器,扩容主节点数量,进一步提升性能。
关键注意事项
- Cluster总线端口 :需开放
16379/16380端口(容器内总线端口),否则节点间无法通信。 - 客户端支持:必须使用Redis Cluster专用客户端(如redis-py-cluster、JedisCluster),普通客户端无法分片。
- 数据分片规则 :Redis根据
CRC16(key) % 16384分配哈希槽,若需指定key到某节点,可使用key{tag}格式(如user{1001}:name)。
此方案通过Redis Cluster实现分布式读写集群,完美利用两台服务器的性能,同时满足业务仅访问8015端口的需求!