实现分布式读写集群(提升两台服务器的性能,支持分片存储+并行读写),Redis Cluster(Redis集群模式)并附排错过程

实现分布式读写集群 (提升两台服务器的性能,支持分片存储+并行读写), 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"));

七、核心优势

  1. 性能提升:数据分片存储在2个主节点,读写请求并行处理,充分利用两台服务器的CPU/内存。
  2. 高可用:每个主节点有从节点备份,主节点故障时自动提升从节点为主,业务无感。
  3. 统一入口 :业务仅需访问8015端口,无需关心集群内部节点。
  4. 弹性扩展:后续可增加服务器,扩容主节点数量,进一步提升性能。

关键注意事项

  1. Cluster总线端口 :需开放16379/16380端口(容器内总线端口),否则节点间无法通信。
  2. 客户端支持:必须使用Redis Cluster专用客户端(如redis-py-cluster、JedisCluster),普通客户端无法分片。
  3. 数据分片规则 :Redis根据CRC16(key) % 16384分配哈希槽,若需指定key到某节点,可使用key{tag}格式(如user{1001}:name)。

此方案通过Redis Cluster实现分布式读写集群,完美利用两台服务器的性能,同时满足业务仅访问8015端口的需求!

相关推荐
dishugj42 分钟前
Linux系统磁盘性能相关命令详解与实例分析
linux·运维·服务器
mn_kw42 分钟前
Spark Shuffle 深度解析与参数详解
大数据·分布式·spark
6***A6631 小时前
SQL 插入数据详解
服务器·数据库·sql
有味道的男人1 小时前
Jumia API
服务器·数据库·microsoft
码农很忙1 小时前
如何选择合适的 Diskless Kafka
分布式·kafka
wadesir1 小时前
Nginx安全加固指南(CentOS系统下的Web服务器安全配置实战)
服务器·nginx·安全
jinxinyuuuus1 小时前
局域网文件传输:P2P架构中的带宽测量与高效率文件分块传输
服务器·架构·p2p
二宝1521 小时前
黑马商城day10-Redis面试篇
数据库·redis·面试
Evan芙1 小时前
Rocky Linux 9 双网卡 bond0 绑定
linux·服务器·网络