Docker Swarm下Redis Sentinel故障转移配置疑问咨询
咱们先把核心问题拆解清楚,结合Docker Swarm和Bitnami Redis的特性一步步分析:
一、Bitnami单主建议 vs Redis官方3主的差异
首先得厘清一个关键区别:Bitnami文档说的「1个主节点」是针对Redis主从复制架构(单主多从,主节点负责写、从节点负责读,数据全量同步),这种模式运维简单,适合中小规模、数据量不大的场景;而Redis官方提到的「至少3个主节点」是针对Redis Cluster分片集群——这种模式会把数据拆分到多个主节点上,目的是横向扩展存储容量,同时保证分片级的高可用。
你当前用的是主从+Sentinel的架构,不是Redis Cluster,所以这俩建议针对的是完全不同的部署模式,别混淆啦。
另外关于你担心的「从节点只读导致故障转移后写入失败」:Bitnami的Redis镜像自带故障转移适配逻辑——当Sentinel把某个从节点提升为主节点后,镜像脚本会自动修改该节点的配置,关闭只读模式。你可以手动测试验证:停掉主节点容器,等Sentinel完成故障转移后,执行redis-cli -h <新主节点IP> -p 6379 -a laSQL2019 config get readonly,结果应该是"no"。
二、全局模式主节点是否需要Sentinel?
绝对不建议把redis-master设为global模式!global模式会在Swarm的每个节点上启动一个独立的Redis主节点,这些主节点之间没有任何数据同步机制,会直接导致数据分裂——比如你在Node1的M1写入数据,Node2的M2上完全看不到,这完全违背了Redis集群的初衷。
正确的高可用做法是:主节点用replicated模式,replicas=1,再通过placement约束(比如constraints: [node.role == manager]或者指定节点标签)把主节点部署到稳定的节点上。这种情况下,Sentinel依然是必须的——它负责监控主节点状态,一旦主节点故障,自动把某个从节点提升为主,同时通知其他从节点切换到新主节点同步数据。
三、你的架构合理性分析
你画的「每个节点都有M、R、S」的架构是不合理的,核心问题就是多主节点没有数据同步,会造成数据不一致。正确的主从+Sentinel架构应该是:
- 1个主节点(Swarm服务,replicated=1,部署在可靠节点)
- 3个左右的从节点(replicated模式,分布在不同Swarm节点,保证冗余)
- 至少3个Sentinel节点(可以用global模式,每个节点一个,或者replicated=3,分布在不同节点)
你的当前Docker配置里,redis-master设为global是核心问题,必须修改。
四、是否需要引入负载均衡?
分场景来看:
- 写请求:必须直接发送到主节点,不需要负载均衡——所有写操作只能由主节点处理,负载均衡反而会出问题(比如把写请求发到从节点会被拒绝)。
- 读请求:如果你的业务是读多写少,引入负载均衡(比如Traefik,或者利用Swarm内置的DNS轮询)把读请求分发到各个从节点,能有效提升读性能,减轻主节点压力,这时候是非常有必要的。
针对你的Docker配置的修改建议
version: '3' services: redis-master: image: 'bitnami/redis:latest' ports: - '6379:6379' environment: - REDIS_REPLICATION_MODE=master - REDIS_PASSWORD=laSQL2019 - REDIS_EXTRA_FLAGS=--maxmemory 100mb volumes: - 'redis-master-volume:/bitnami' deploy: mode: replicated replicas: 1 # 约束主节点部署在manager节点(可根据集群规划调整) placement: constraints: [node.role == manager] redis-slave: image: 'bitnami/redis:latest' ports: - '6379' depends_on: - redis-master volumes: - 'redis-slave-volume:/bitnami' environment: - REDIS_REPLICATION_MODE=slave - REDIS_MASTER_HOST=redis-master - REDIS_MASTER_PORT_NUMBER=6379 - REDIS_MASTER_PASSWORD=laSQL2019 - REDIS_PASSWORD=laSQL2019 - REDIS_EXTRA_FLAGS=--maxmemory 100mb deploy: mode: replicated replicas: 3 # 让从节点分布在不同节点,避免单点故障 placement: spread: [node.id] redis-sentinel: image: 'bitnami/redis:latest' ports: - '16379' depends_on: - redis-master - redis-slave volumes: - 'redis-sentinel-volume:/bitnami' entrypoint: | bash -c 'bash -s <<EOF "/bin/bash" -c "cat <<EOF > /opt/bitnami/redis/etc/sentinel.conf port 16379 dir /tmp sentinel monitor master-node redis-master 6379 2 sentinel down-after-milliseconds master-node 5000 sentinel parallel-syncs master-node 1 sentinel failover-timeout master-node 5000 sentinel auth-pass master-node laSQL2019 sentinel announce-ip redis-sentinel sentinel announce-port 16379 EOF" "/bin/bash" -c "redis-sentinel /opt/bitnami/redis/etc/sentinel.conf" EOF' deploy: mode: replicated replicas: 3 # Sentinel节点分布在不同节点,保证集群高可用 placement: spread: [node.id] volumes: redis-master-volume: driver: local redis-slave-volume: driver: local redis-sentinel-volume: driver: local
几个关键修改点:
- 把redis-master改成
replicated:1,增加placement约束保证稳定性 - 把redis-slave的replicas设为3,增加spread约束让它们分布在不同节点
- 把redis-sentinel改成
replicated:3,同样分布在不同节点,避免Sentinel单点故障
内容的提问来源于stack exchange,提问作者Soham Dasgupta

