Redis 7.0 高可用集群实战:Docker网络优化与配置注入

Redis作为高性能内存数据库,在现代应用架构中扮演着至关重要的角色。然而,单点故障的风险始终悬在头顶。为了确保服务的持续稳定,构建一个高可用的Redis集群是每个后端开发者的必修课。

今天,我们将直接跳过繁琐的手动配置,利用Docker的强大能力,一键搭建一套生产级别的Redis 7.0主从哨兵集群。这套方案不仅引入了自定义网络来确保通信的稳健性,还采用了“配置注入”的黑科技,让你在享受极致部署速度的同时,深入理解其背后的架构原理。

为什么选择“主从+哨兵”?

在深入实操之前,我们需要明确这个架构的核心价值。单纯的主从复制虽然能实现数据备份和读写分离,但它有一个致命弱点:当主节点挂掉时,它无法自动选举新的主节点。这意味着一旦主库宕机,整个写入服务就会瘫痪,必须人工介入恢复。

而哨兵模式正是为了解决这个问题而生。它是Redis官方推荐的高可用解决方案,其核心职责包括:

  • 监控: 哨兵会不断地检查你的主节点和从节点是否运作正常。
  • 通知: 当某个节点出现问题时,哨兵可以通过API通知管理员或其他应用程序。
  • 自动故障转移: 这是最关键的功能。当主节点挂掉后,哨兵集群会通过投票机制,自动将一个从节点提升为新的主节点,并让其他的从节点去复制新的主节点,从而实现无缝切换。

简单来说,我们的目标是打造一个“打不死的小强”系统:主节点负责写,从节点负责读,而三个哨兵则像忠诚的卫士一样时刻监控,一旦主节点倒下,立即自动扶正从节点,确保服务不中断。

架构升级:Docker网络与动态配置的魅力

本次实战我们不仅仅满足于让容器“跑起来”,而是追求更优的工程化实践。

首先是自定义Docker网络。在旧版本的脚本中,我们可能依赖默认的网桥,但在多容器交互时,显式创建一个专用网络(如redis-net)是更佳实践。这就好比在一个大办公室里,虽然我们都在同一栋楼(宿主机),但为了沟通效率,我们专门拉了一根内部电话线。在这个网络下,容器可以通过容器名直接进行DNS解析,无需关心具体的IP地址变动,极大地提升了集群的鲁棒性。

其次是配置注入技术。传统的哨兵部署往往需要编写单独的sentinel.conf文件并挂载进容器,这不仅繁琐,还容易在宿主机留下垃圾文件。我们将采用Shell脚本中的heredoc语法,在容器启动的瞬间动态生成配置文件。这种方式既保留了配置的灵活性,又让脚本变得自包含且整洁。

Windows用户特别说明

重要提醒: 如果你使用的是Windows系统(Docker Desktop),由于Docker运行在WSL2虚拟机中,标准的Bridge网络模式会导致哨兵无法正确识别宿主机IP,从而引发连接问题。

对于Windows用户,建议直接使用下方的Host网络版本脚本,它能让你通过127.0.0.1直接访问所有服务,体验最顺畅。

Windows/Linux Host模式通用脚本:

#!/bin/bash

echo "============================================="
echo "    Redis 7.0 一主一从 + 三哨兵(Host网络)"
echo "         Windows 本地模拟哨兵专用"
echo "============================================="

echo -e "\n[1/6] 停止旧容器..."
docker rm -f redis-master redis-slave sentinel1 sentinel2 sentinel3 2>/dev/null

echo -e "\n[2/6] 启动主节点(端口:6379)"
docker run -d \
  --name redis-master \
  --network=host \
  --restart=always \
  redis:7.0 \
  redis-server --protected-mode no

echo -e "\n[3/6] 启动从节点(端口:6380)"
docker run -d \
  --name redis-slave \
  --network=host \
  --restart=always \
  redis:7.0 \
  redis-server --protected-mode no --slaveof 127.0.0.1 6379

echo -e "\n[4/6] 启动哨兵1(端口:26379)"
docker run -d \
  --name sentinel1 \
  --network=host \
  --restart=always \
  redis:7.0 \
  redis-sentinel --port 26379 --sentinel monitor mymaster 127.0.0.1 6379 2 --sentinel down-after-milliseconds mymaster 5000 --sentinel failover-timeout mymaster 10000

echo -e "\n[5/6] 启动哨兵2(端口:26380)"
docker run -d \
  --name sentinel2 \
  --network=host \
  --restart=always \
  redis:7.0 \
  redis-sentinel --port 26380 --sentinel monitor mymaster 127.0.0.1 6379 2 --sentinel down-after-milliseconds mymaster 5000 --sentinel failover-timeout mymaster 10000

echo -e "\n[6/6] 启动哨兵3(端口:26381)"
docker run -d \
  --name sentinel3 \
  --network=host \
  --restart=always \
  redis:7.0 \
  redis-sentinel --port 26381 --sentinel monitor mymaster 127.0.0.1 6379 2 --sentinel down-after-milliseconds mymaster 5000 --sentinel failover-timeout mymaster 10000

sleep 3

echo -e "\n============================================="
echo "  启动完成!"
echo " 主节点:127.0.0.1:6379"
echo " 从节点:127.0.0.1:6380"
echo " 哨兵:26379、26380、26381"
echo " 网络模式:host(Windows 可直接访问)"
echo "============================================="

echo -e "\n 哨兵状态:"
docker exec sentinel1 redis-cli -p 26379 info sentinel
Linux/Mac环境部署脚本

如果你是在Linux服务器或Mac环境下运行,推荐使用下面的标准网络隔离版本。它更加严谨,适合模拟真实的云原生环境。

你可以将以下代码保存为redis-cluster-pro.sh。这个脚本经过了精心打磨,它不仅会自动清理旧环境、创建网络,还会处理复杂的哨兵配置逻辑。

#!/bin/bash

# ==========================================
# Redis 7.0 高可用集群部署脚本 (v2.0)
# 特性:Docker网络隔离 + 动态配置注入
# ==========================================

echo "============================================="
echo "    Redis 7.0 一主一从 + 三哨兵 高可用集群"
echo "            启动中,请稍候..."
echo "============================================="

# 1. 清理环境
echo -e "\n[1/5] 清理旧容器和网络..."
docker rm -f redis-master redis-slave sentinel1 sentinel2 sentinel3 >/dev/null 2>&1
docker network rm redis-net 2>/dev/null

# 2. 创建专用网络
echo -e "\n[2/5] 创建Docker网络 (redis-net)..."
docker network create redis-net >/dev/null 2>&1

# 3. 启动主节点
echo -e "\n[3/5] 启动主节点(端口 6379)..."
docker run -d --name redis-master \
  --network redis-net \
  -p 6379:6379 \
  redis:7.0 \
  redis-server --protected-mode no >/dev/null 2>&1

# 4. 启动从节点
echo -e "\n[4/5] 启动从节点(端口 6380)..."
docker run -d --name redis-slave \
  --network redis-net \
  -p 6380:6379 \
  redis:7.0 \
  redis-server --protected-mode no --replicaof redis-master 6379 >/dev/null 2>&1

sleep 5

# 获取主节点在 redis-net 网络中的 IP
IP=$(docker inspect redis-master | grep '"IPAddress"' | head -1 | cut -d '"' -f 4)

# 5. 启动哨兵集群
echo -e "\n[5/5] 启动 3 个哨兵节点..."
echo "  → 哨兵1:26379"
echo "  → 哨兵2:26380"
echo "  → 哨兵3:26381"

# 定义哨兵启动的通用命令模板,减少重复代码
start_sentinel() {
    local name=$1
    local port=$2
    docker run -d --name $name \
      --network redis-net \
      -p $port:26379 \
      redis:7.0 \
      sh -c "
cat > /sentinel.conf << 'CONF'
port 26379
protected-mode no
dir /tmp
sentinel monitor mymaster $IP 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 10000
CONF
redis-server /sentinel.conf --sentinel
" >/dev/null 2>&1
}

# 依次启动三个哨兵
start_sentinel "sentinel1" "26379"
start_sentinel "sentinel2" "26380"
start_sentinel "sentinel3" "26381"

sleep 2

# 最终状态汇报
echo -e "\n============================================="
echo "     Redis 高可用集群启动成功!"
echo "    主节点:6379"
echo "    从节点:6380"
echo "    哨兵节点:26379、26380、26381"
echo "============================================="

echo -e "\n 集群状态检查:"
docker exec sentinel1 redis-cli -p 26379 info sentinel | grep master0

echo -e "\n 全部完成!现在可以开始测试故障转移了。"
核心技术点深度解析

在这个脚本中,有几个细节值得你细细品味,它们也是很多初学者容易踩坑的地方。

第一点是网络隔离与DNS解析。通过docker network create redis-net--network redis-net参数,我们构建了一个独立的沙箱。在这个网络里,redis-slave可以直接ping通redis-master,而不需要硬编码IP地址。这对于容器的重启和迁移非常友好,因为无论Docker分配什么内部IP,服务名永远指向正确的容器。

第二点是动态配置注入。请注意看哨兵启动部分的sh -c "cat > ..."代码块。这是一种非常优雅的“无中生有”技巧。我们没有在宿主机创建.conf文件然后挂载进去,而是直接在容器启动的那一毫秒,利用Shell指令在容器内部写入了配置文件。这样做的好处是脚本是自包含的,不会在宿主机留下垃圾文件,非常适合临时测试环境的快速搭建与销毁。

第三点是变量替换的艺术。在heredoc中,我们使用了<< 'CONF'(带单引号)。这通常意味着“原样输出,不解析变量”。但是,为了让哨兵能获取到主节点的动态IP($IP),我们在脚本层面巧妙地处理了上下文。实际上,在上述脚本中,$IP是在外层Shell获取的,因此在sh -c的双引号包裹下,它能被正确替换进配置文件内容中,而配置文件内部的其他变量则保持原样。

实战项目配置

验证你的成果

当脚本运行结束,看到绿色的“全部完成”提示后,不要急着关闭终端。让我们再次确认一下主从同步和高可用状态。

首先,我们可以尝试向主节点写入数据,然后去从节点读取,验证数据的一致性。如果一切正常,你应该能瞬间看到刚才写入的数据,这证明主从复制通道已经畅通无阻。

接下来是最激动人心的环节——模拟故障转移。执行docker stop redis-master强制停止主节点。此时,观察哨兵的日志,你会看到它们迅速感知到主节点下线,并开始选举新的领导者。几秒钟后,原本的从节点会自动晋升为主节点,接管所有的读写请求。这种自我修复的能力,正是分布式系统最迷人的地方。

掌握这一套基于Docker网络和动态配置的部署方式,你对Redis高可用架构的理解将不仅仅停留在理论层面,而是真正具备了工程落地的能力。

更多推荐