
写在前面上周给客户搭生产就一台 CentOS 7.9 的机子Redis 还得有高可用。本来想单机凑合一下算了结果客户不同意说必须能自动切换。行吧最后就搞了个 1 主 2 从 3 哨兵全部塞 Docker 里跑。步骤都不难就是哨兵那块把我坑了小半天一直连不上日志看着又没啥异常。绕了一圈才发现是announce-ip没配。写下来给自己留个档也顺便给踩同样坑的人省点时间。环境CentOS 7.9Docker 24.0.5Redis 镜像用的redis:7.2.4服务器 IP 假设是192.168.1.100你们换成自己的目录先建好配置和数据都挂宿主机别偷懒。容器一重启数据没了哭都来不及。mkdir -p /app/redis/{master,slave1,slave2}/{conf,data} mkdir -p /app/redis/sentinel/{s1,s2,s3}/conf主节点配置cd /app/redis/master/conf vim redis.conf只留关键的几项其他默认就行bind 0.0.0.0 port 6379 protected-mode no daemonize no appendonly yes requirepass Redis2025 masterauth Redis2025注意daemonize一定是no。Docker 要前台进程守着你写 yes 容器起来立马就挂一开始不知道的话看日志还挺懵的。从节点配置两个从节点几乎一模一样就replicaof那行指向主节点。slave1的bind 0.0.0.0 port 6379 protected-mode no daemonize no appendonly yes requirepass Redis2025 masterauth Redis2025 replicaof 192.168.1.100 6379slave2复制一份就行容器内端口都是 6379宿主机映射不同端口。主从先跑起来docker run -d --name redis-master \ --restartalways \ -p 6379:6379 \ -v /app/redis/master/conf/redis.conf:/etc/redis/redis.conf \ -v /app/redis/master/data:/data \ redis:7.2.4 redis-server /etc/redis/redis.conf docker run -d --name redis-slave1 \ --restartalways \ -p 6380:6379 \ -v /app/redis/slave1/conf/redis.conf:/etc/redis/redis.conf \ -v /app/redis/slave1/data:/data \ redis:7.2.4 redis-server /etc/redis/redis.conf docker run -d --name redis-slave2 \ --restartalways \ -p 6381:6379 \ -v /app/redis/slave2/conf/redis.conf:/etc/redis/redis.conf \ -v /app/redis/slave2/data:/data \ redis:7.2.4 redis-server /etc/redis/redis.conf验证一下主从有没有连上docker exec -it redis-master redis-cli -a Redis2025 info replication看到role:master和connected_slaves:2主从就 OK 了。哨兵配置我踩坑的地方三个哨兵配置基本一样就端口不一样。s1 的vim /app/redis/sentinel/s1/conf/sentinel.confport 26379 daemonize no sentinel monitor mymaster 192.168.1.100 6379 2 sentinel auth-pass mymaster Redis2025 sentinel down-after-milliseconds mymaster 5000 sentinel failover-timeout mymaster 10000 sentinel announce-ip 192.168.1.100 sentinel announce-port 26379重点看下面这两行sentinel announce-ip 192.168.1.100 sentinel announce-port 26379我一开始就是没这两行然后就出现一个很邪门的现象哨兵之间能互相发现主从也识别正常但是 Spring Boot 客户端连上来一操作就报错说连不上从节点。去哨兵里看了下好家伙返回给客户端的从节点 IP 是172.17.0.x这种 Docker 内部网络的地址客户端能连上才怪。加上announce-ip明确告诉哨兵你对外说的时候就说自己是 192.168.1.100问题就解决了。这个坑真的太隐蔽了日志里什么错都不报。s2、s3 一样的配置端口改成 26380、26381。哨兵起起来docker run -d --name redis-sentinel-1 \ --restartalways \ -p 26379:26379 \ -v /app/redis/sentinel/s1/conf/sentinel.conf:/etc/redis/sentinel.conf \ redis:7.2.4 redis-sentinel /etc/redis/sentinel.conf docker run -d --name redis-sentinel-2 \ --restartalways \ -p 26380:26379 \ -v /app/redis/sentinel/s2/conf/sentinel.conf:/etc/redis/sentinel.conf \ redis:7.2.4 redis-sentinel /etc/redis/sentinel.conf docker run -d --name redis-sentinel-3 \ --restartalways \ -p 26381:26379 \ -v /app/redis/sentinel/s3/conf/sentinel.conf:/etc/redis/sentinel.conf \ redis:7.2.4 redis-sentinel /etc/redis/sentinel.confs2、s3 容器里哨兵还是监听 26379宿主机端口不一样就行但配置文件里的port和announce-port记得跟着改。试试故障切换进哨兵看下状态docker exec -it redis-sentinel-1 redis-cli -p 26379 127.0.0.1:26379 sentinel master mymaster看到num-slaves是 2、num-other-sentinels是 2整个链路就串起来了。然后手动把主节点弄挂docker stop redis-master等个五到十秒再看docker exec -it redis-sentinel-1 redis-cli -p 26379 sentinel master mymasterip那行如果变成某个 slave 的地址说明切换成功了稳。Java 客户端配置顺手贴下 Spring Boot 的配置别直连主节点走哨兵才有意义spring: data: redis: password: Redis2025 sentinel: master: mymaster nodes: - 192.168.1.100:26379 - 192.168.1.100:26380 - 192.168.1.100:26381最后说两句整个流程其实就announce-ip那里坑人其他都挺顺的。如果你搭完发现客户端连不上先去哨兵里看下sentinel slaves mymaster看看返回的 IP 是不是内网的 172 开头是的话就是这个问题。另外说句实话单机部一堆容器搞高可用属于自娱自乐机器一挂全完蛋。真上生产还是老老实实拿几台机器分开部。这个方案凑合适合测试环境或者临时过渡。有问题评论区聊。