必须显式配置 replica-announce-ip 和 sentinel announce-ip,否则从节点与哨兵在 docker 环境中默认广播内网 ip(如 172.20.0.3),导致主节点、其他哨兵及外部客户端无法连通,故障转移失败或客户端获取错误地址。

redis-server 启动时必须显式设 replica-announce-ip,否则从节点在 INFO replication 里暴露的是容器内网 IP
从节点启动后,主节点通过 INFO replication 获取其地址,默认用的是它连接主节点时的 socket peer IP(比如 172.20.0.3)。这个地址在 Docker bridge 网络里对外不可达,哨兵拿到后直连失败,状态卡在 connecting 或 down。
解决方式是强制从节点“自报家门”为服务名或宿主机可路由地址:
-
replica-announce-ip必须设为该服务在 Compose 中定义的service name(如redis-slave1),不能写localhost或127.0.0.1 - 如果从节点需被外部客户端直连(如本地 IDE 连 Redis GUI 工具),才考虑填宿主机真实 IP(如
192.168.1.100),但要同步开放对应端口和防火墙 - 对应端口用
replica-announce-port,值必须与容器内监听端口一致(默认6379),不是宿主机映射端口(如6380) - 命令行启动示例:
redis-server --port 6379 --replica-of redis-master 6379 --replica-announce-ip redis-slave1 --replica-announce-port 6379
redis-sentinel 启动前必须配置 sentinel announce-ip,否则 SENTINEL get-master-addr-by-name 返回内网地址
哨兵自身也要“声明身份”。它默认用绑定网卡的 IP(如 172.20.0.5)作为自己的地址写入主节点的 sentinel:hello 频道,并返回给客户端。外部客户端拿到这个地址后无法建立 TCP 连接,redis-cli -p 26379 SENTINEL get-master-addr-by-name mymaster 返回的 ip 字段就错了。
这个配置不能靠 CONFIG SET 运行时修改,必须出现在 sentinel.conf 文件中或启动参数里:
-
sentinel announce-ip填客户端能直接访问到哨兵的地址:Docker 内部通信填服务名(如sentinel1),外部访问填宿主机 IP 或 SLB 地址 -
sentinel announce-port必须与哨兵实际监听端口一致(默认26379),若用了-p 26380:26379映射,这里就得填26380 - 配置文件中必须同时有
bind 0.0.0.0(或具体网卡 IP),否则哨兵进程收不到其它节点发来的命令 - 示例配置段:
sentinel monitor mymaster redis-master 6379 2<br>sentinel down-after-milliseconds mymaster 5000<br>sentinel failover-timeout mymaster 60000<br>sentinel announce-ip sentinel1<br>sentinel announce-port 26379
docker-compose.yml 中 service name 是 DNS 名,hostname 不可靠
Docker Compose 内置 DNS 会把每个 service 名解析为对应容器 IP,但 hostname: 字段不参与 DNS 注册,仅影响容器内 /etc/hosts 和 hostname 命令输出。很多配置误写 hostname: redis-slave1,结果 replica-announce-ip 设成这个值,却无法被其它容器解析。
正确做法只依赖 service 名:
- 主节点服务定义为
redis-master,所有从节点和哨兵的配置里都用这个字符串作 host -
replica-of redis-master 6379、sentinel monitor mymaster redis-master 6379 2、replica-announce-ip redis-slave1—— 全部用 service name - 不要启用
host网络模式,它绕过内置 DNS,导致服务名无法解析 - 验证 DNS 是否生效:
docker exec -it sentinel1 ping -c 1 redis-master应成功
端口映射冲突会导致哨兵间通信中断
三个哨兵容器如果都映射到宿主机同一端口(如全写 - "26379:26379"),只有第一个能绑定成功,其余启动失败或监听异常。更隐蔽的问题是:即使容器内都监听 26379,但宿主机上只暴露一个端口,外部客户端或其它哨兵只能访问其中一个,SENTINEL sentinels mymaster 查不到全部节点,故障转移无法达成 quorum。
必须保证每个哨兵在宿主机上有唯一可访问端口:
- 使用不同宿主机端口映射同一容器端口:
- "26379:26379"、- "26380:26379"、- "26381:26379" - 对应的
sentinel announce-port要随之改为26379、26380、26381(因为这是客户端连它的入口) - 哨兵之间通信走 Docker 内网(如
sentinel1:26379→sentinel2:26379),不受宿主机端口映射影响,所以它们的announce-port可统一设为26379,只要容器内监听正常即可;但对外提供服务的 announce-port 必须匹配宿主机暴露端口
配置错一个 announce-ip,整个哨兵集群就可能“看不见彼此”,问题表象是主节点状态为 sdown 却不触发故障转移,或者客户端始终连不上新主节点 —— 根本原因往往不在逻辑,而在网络层那行被忽略的声明。











