docker compose 部署 Redis Cluster 高可用(三主三从)

 

 

Redis Cluster(三主三从) VS Redis Sentinel(一主两从三哨兵)

---------------------------------------------------------------------------------------

Redis Cluster(三主三从)

架构特点:

主节点1 (0-5460槽) → 从节点1
主节点2 (5461-10922槽) → 从节点2  
主节点3 (10923-16383槽) → 从节点3
↑ ↑ ↑
客户端直接连接

适用场景:

  • 大数据量:数据超过单机内存容量
  • 高并发写:需要多个主节点分担写入压力
  • 水平扩展:可通过增加主节点来扩展写能力
  • 数据分片:天然支持数据分布式存储

----------------------------------------------------------------------------------------

Redis Sentinel(一主两从三哨兵

架构特点:

主节点 (全部数据)
↑
从节点1 ← 复制 → 从节点2 ← 复制 → 从节点3
↑ ↑ ↑
哨兵集群监控

工作原理:

  1. 3个哨兵 监控主节点健康状态
  2. 多数哨兵 认为主节点下线时触发故障转移
  3. 选举新的主节点,其他从节点切换到新主节点

适用场景:

  • 中等数据量:数据能在单机内存放下
  • 读多写少:可通过多个从节点分担读压力

-------------------------------------------------------------------------------------------

 

 

架构概览

特性

Redis Cluster

Redis Sentinel

数据分布

自动分片 (16384个槽位)

单一数据集

写扩展性

✅ 支持 (多主节点)

❌ 不支持 (单主节点)

故障转移

内置自动故障转移

通过哨兵监控和切换

客户端复杂度

较高 (需支持集群协议)

较低

 

-------------------------------------------------------------------------------------------

 

部署 Redis Cluster 三主三从

环境信息 (以下部署 docker网络模式为host 端口映射会影响集群正常启动

ip

端口

作用

192.168.219.130

16001

master1

192.168.219.132

16001

master2

192.168.219.133

16001

master3

192.168.219.130

16002

slave1

192.168.219.132

16002

slave2

192.168.219.133

16002

slave3

 

一、环境准备

#设置主机名称 
hostnamectl set-hostname node1 #不同机器设置不同的

#关闭防火墙和selinux (不关闭vip 无法飘逸)
systemctl stop firewalld.service
systemctl disable firewalld.service
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
 

 

二、redis配置文件准备

2.1 目录信息

[root@node2 redis]# tree
.
├── master
│   └── redis1.conf
├── redis.yml
├── redis_status.sh
└── slave
└── redis2.conf

 

 

2.2 redis配置文件和启动yml文件信息 (每台机器一样)

2.2.1 master 配置文件 :去注释,注释只是让你能看懂。加上可能无法启动


bind 0.0.0.0
port 6379
# 不以守护进程方式运行,适合Docker容器环境
daemonize no  
# Redis工作目录,用于存放数据文件和日志
dir /data  
# 进程ID文件路径,用于记录Redis进程的PID
pidfile /var/run/redis_6379.conf  
# 启用Redis集群模式
cluster-enabled yes  
# 集群节点超时时间(毫秒),超过此时间认为节点不可用
cluster-node-timeout 5000
# 集群节点配置文件路径,保存集群拓扑信息
cluster-config-file /data/nodes-6379.conf
# 集群节点通讯超时时间(毫秒)
cluster-node-timeout 5000  
# 客户端连接Redis服务器所需的认证密码
requirepass 123456789
# 从节点连接主节点时使用的认证密码
masterauth 123456789
# 启用AOF(Append Only File)持久化模式
appendonly yes  
# AOF持久化文件名
appendfilename "appendonly.aof"
# AOF文件同步策略:每秒同步一次,兼顾性能和数据安全
appendfsync everysec
# 内存不足时的键淘汰策略:在所有键中淘汰最近最少使用的键
maxmemory-policy allkeys-lru
# 关闭保护模式,允许远程连接(配合bind和密码使用)
protected-mode no
# TCP keepalive时间(秒),检测连接是否存活
tcp-keepalive 300            

 

 

2.2.2 slave 配置文件


bind 0.0.0.0
port 6379

daemonize no
dir /data
pidfile /var/run/redis_6379.conf
cluster-enabled yes
cluster-node-timeout 5000
cluster-config-file /data/nodes-6379.conf
requirepass 123456789
masterauth 123456789
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
maxmemory-policy allkeys-lru
tcp-keepalive 300
protected-mode no

 

 

2.2.3 启动文件



version: '3.8'
services:
  redis10:
    image: redis:8.2.0
    container_name: redis1
    restart: always
    volumes:
      - ./master/redis.conf:/etc/redis.conf
      - ./master/data:/data           
    command: redis-server /etc/redis.conf
    ports:
      - "6379:6379"
    networks:
      my-test:
        ipv4_address: 10.100.100.10    #指定容器ip  ,便于后面一台机器出现两个master情况

  redis11:
    image: redis:8.2.0
    container_name: redis2
    restart: always
    volumes:
      - ./slave/redis.conf:/etc/redis.conf
      - ./slave/data:/data          
    command: redis-server /etc/redis.conf
    ports:
      - "6380:6379"
    networks:
      my-test:
        ipv4_address: 10.100.100.11     #指定容器ip  ,便于后面一台机器出现两个master情况

networks:
  my-test:
    external: true

 

 

 

三、启动

docker compose -f redis.yml up -d 

 

image

 

四、配置集群

4.1 随便进入一个master容器

docker exec -it redis10 bash

 

4.2 配置集群(根据实际修改ip端口

redis-cli -a '123456789' --cluster create \
  192.168.219.130:16001 \
  192.168.219.132:16001 \
  192.168.219.133:16001 \
  192.168.219.130:16002 \
  192.168.219.132:16002 \
  192.168.219.133:16002 \
  --cluster-replicas 1

image

 

 

 

4.3 查看集群状态

4.3.1 查询集群状态

redis-cli -c -a '123456789' -p 6379  cluster info

4.3.2 查询节点状态

redis-cli -c -a '123456789' -p 6379 cluster nodes

image

 

 

 

五、测试可用性(停用主从节点在启动)

集群创建成功后。 链接redis需要加-c 参数,完整:

redis-cli -c -a '123456789' -p 6379

 

5.1 停 一个机器节点

5.1.1 随便停用一个机器节点

docker stop redis10 redis11

 

 

5.1.2 查看master日志 有报错已经断开

image

 

 

5.1.3 在启动从节点

docker start redis11 redis10 

 

 

5.1.4 查看master日志 有报错已经链接

image

 

 

 

 

 

 

 

5.3 写入数据测试并验证

集群总共有 16384 个槽位 (slots)

  • 节点1: 负责槽位 0-5460
  • 节点2: 负责槽位 5461-10922
  • 节点3: 负责槽位 10923-16383

 

在任意一台master写入一条数据。跳过进入容器进入redis步骤

这里我是在node2节点插入。可以发现这条数据在5535槽

 SET employee:001 '{"name":"王五","department":"技术部"}'
 CLUSTER KEYSLOT employee:001

 

 

查看槽信息

 CLUSTER SLOTS

可以看到 一节点是219.130:16001和219.132:16002 对应槽是0-5460

 

 

 

node1节点执行 查询数据会自动跳转到对应数据节点

GET employee:001
DEL employee:001   #删除刚创建的数据

 

 

停节点 启节点都能正常恢复,数据也能在其他节点能看到

 

 

 

 

六、Java程序连接redis集群

spring:
  redis:
    cluster:
      nodes:
        - 192.168.99.199:16001
        - 192.168.99.199:16002
        - 192.168.99.199:16003
        - 192.168.99.199:16004
        - 192.168.99.199:16005
        - 192.168.99.199:16006
      max-redirects: 5
    password: 123456789
    prefix: ssdev-pamirs
    timeout: 20000ms
    lettuce:
      pool:
        max-active: 8
        max-idle: 8
        min-idle: 2
        max-wait: -1ms

 

 

七、自动检测本机是否有两个master。 如果有两个 就停一个服务,让其master飘逸到其他地方

当一台机器有两个master。 这台机器挂掉会导致集群无法使用

 redis_status.sh

 

#!/bin/bash

aaa=0

main_loop() {
if [[ "$aaa" == 0 ]];then
  #指定容器里的ip
  ipip1=10.100.100.10
  ipip2=10.100.100.11
  #指定两个容器名
  redisname=redis1
  redisname2=redis2
  #指定redis密码
  redispass=123456789
  #检测本机是否存在2个master
  master_sum=$(docker exec -i $redisname redis-cli -a "$redispass" -p 6379   cluster nodes    | grep -E "$ipip1|$ipip2"  |grep master |wc -l)
  fail_sum=$(docker exec -i $redisname redis-cli -a "$redispass" -p 6379   cluster nodes  |grep fail |wc -l)
  if [[ "$master_sum" == 2  ]];then
   #判断所有节点是否有失败节点,没有就证明集群正常启动
    if [[ "$fail_sum" == 0 ]];then
       aaa=1
       docker stop $redisname2
       sleep 10
       docker start $redisname2
       aaa=0
    fi
  fi
fi
}

while true; do
    main_loop
    sleep 5
done
后台运行脚本

nohup redis_status.sh > /dev/null 2>&1 &

关闭

ps -ef |grep redis_status.sh

kill -9 ****

 

posted @ 2025-10-23 10:28  mrdongdong  阅读(14)  评论(0)    收藏  举报