未来星球 未来星球
  • 首页
  • 新闻资讯
  • 技术教程
  • 软件工具
  • 知识百科
  • 生活实用
  • 个人随笔
  • 生命外星人
首页 › 技术教程 › 用Redis 8搭一主两从自动切换:4份配置,和3个必然踩到的坑
  • 0
  • 0

用Redis 8搭一主两从自动切换:4份配置,和3个必然踩到的坑

admin
18 小时前
7 views
用Redis 8搭一主两从自动切换:4份配置,和3个必然踩到的坑-未来星球

主库挂掉的那一刻,最难受的不是数据丢了,是应用还在往一个已经不存在的地址写。连接池里的连接还没超时,请求一个个失败,日志里全是”connection refused”,而备库安静地站在旁边,谁也不知道它该接班。

Redis 主从复制本身不带故障切换。哨兵(Sentinel)就是补这一块的:它不存数据,只负责盯着、投票、改写配置,然后告诉客户端”现在该连谁”。

这篇用一个能在一台机器上跑完的最小拓扑,把整条链路搭起来,最后拿一次真实的杀进程演练验证。版本:Redis 8.0.2,redis-py 5.0.8,Docker 27.3。

1. 拓扑:一主两从,三个哨兵

三个 Redis 实例(6380 主、6381/6382 从),三个哨兵(26380/26381/26382)。哨兵必须是奇数个,且至少三个——两个哨兵的情况下,网络一分区就谁也不敢做主。

目录结构长这样:

redis-sentinel-lab/
├── docker-compose.yml
├── conf/
│   ├── master.conf
│   ├── replica.conf
│   ├── sentinel-1.conf
│   ├── sentinel-2.conf
│   └── sentinel-3.conf
└── data/
    ├── 6380/ 6381/ 6382/
    └── s1/ s2/ s3/

单机跑三个实例只是省机器,不代表它能扛住机器级故障。生产上三个哨兵必须落在三台不同的物理机或可用区,否则断电一次,投票机制跟着一起消失。

2. 主库配置:密码、持久化、复制积压

conf/master.conf,完整内容如下。注意 requirepass 和 masterauth 都写了同一个密码——这一行是后面切换能不能成功的关键,先记住它。

port 6380
bind 0.0.0.0
protected-mode no
daemonize no
dir /data

requirepass Er7pLq2mSx
masterauth Er7pLq2mSx

appendonly yes
appendfsync everysec
save 900 1
save 300 10

repl-backlog-size 64mb
repl-diskless-sync yes
repl-diskless-sync-delay 5

maxmemory 2gb
maxmemory-policy noeviction

repl-backlog-size 默认只有 1MB,主库写入一密集,从库断线重连就得全量同步。把它调到 64MB,是为了让”短暂抖动”不至于演变成一次全量拷贝。

maxmemory-policy 用 noeviction 是有意的:当 Redis 既是缓存又是队列时,静默淘汰比报错更难查。

3. 从库配置:只差一行

conf/replica.conf 和主库几乎一样,只改端口,加一行指向主库。其余保持一致,是为了让任何一个从库被提升为主库之后,配置不需要再改。

port 6381
bind 0.0.0.0
protected-mode no
daemonize no
dir /data

requirepass Er7pLq2mSx
masterauth Er7pLq2mSx

replicaof 127.0.0.1 6380
replica-read-only yes
replica-serve-stale-data yes

appendonly yes
appendfsync everysec
repl-backlog-size 64mb

maxmemory 2gb
maxmemory-policy noeviction

6382 那份把 port 改成 6382 即可。replica-serve-stale-data yes 意味着从库和主库失联时仍然返回旧数据——这个设置适合读多写少的场景,但它会让”读到过期数据”变成一件安静发生的事。

4. 哨兵配置:三份只差端口

conf/sentinel-1.conf。哨兵的配置文件必须可写,运行时会自己往里追加状态。不要用 ConfigMap 挂只读文件,否则哨兵启动就报错退出。

port 26380
bind 0.0.0.0
protected-mode no
daemonize no
dir /data

sentinel monitor mymaster 127.0.0.1 6380 2
sentinel auth-pass mymaster Er7pLq2mSx
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
sentinel deny-scripts-reconfig yes
sentinel resolve-hostnames no
sentinel announce-ip 127.0.0.1
sentinel announce-port 26380

几个数字要说清:2 是法定票数,三个哨兵里两个同意才判定主库下线;5000 是主观下线的时间窗,5 秒没回应就先标记为可疑;60000 是一次切换的总超时;parallel-syncs 1 让从库一个一个同步,避免切换瞬间主库被全量同步打满。

announce-ip 和 announce-port 这两行,在单机实验里看着多余,但它们是容器和 NAT 环境里最容易出事的地方,下面第三个坑专门讲。

sentinel-2 和 sentinel-3 把 port 与 announce-port 改成 26381、26382,其余不变。

5. 起服务与第一轮验收

docker-compose.yml 用同一个镜像起六个容器,把配置和数据目录挂进去:

services:
  redis-master:
    image: redis:8.0.2
    command: ["redis-server", "/conf/master.conf"]
    ports: ["6380:6380"]
    volumes:
      - ./conf:/conf:ro
      - ./data/6380:/data

  redis-replica-1:
    image: redis:8.0.2
    command: ["redis-server", "/conf/replica.conf"]
    ports: ["6381:6381"]
    volumes:
      - ./conf:/conf:ro
      - ./data/6381:/data

  sentinel-1:
    image: redis:8.0.2
    command: ["redis-sentinel", "/conf/sentinel-1.conf"]
    ports: ["26380:26380"]
    depends_on: [redis-master]
    volumes:
      - ./conf:/conf
      - ./data/s1:/data

(6382 与 sentinel-2/3 按同样结构补齐。sentinel 的 conf 目录不能挂 :ro,理由同上。)

docker compose up -d
docker compose ps

起来之后先验三件事,顺序不要乱:

  1. 主库能写:redis-cli -p 6380 -a Er7pLq2mSx SET k v
  2. 从库同步正常:redis-cli -p 6381 -a Er7pLq2mSx INFO replication,看到 master_link_status:up,且 master_last_io_seconds_ago 小于 2
  3. 哨兵认得主库:redis-cli -p 26380 SENTINEL get-master-addr-by-name mymaster,返回 127.0.0.1 和 6380

三步都过,再看哨兵之间的互相发现:SENTINEL sentinels mymaster 应该列出另外两个哨兵的地址。如果这里是空的,说明哨兵之间没握上手,后面永远凑不齐两票。

6. 演练:把主库杀掉

用 docker compose stop redis-master,然后盯住任意一个哨兵的日志:

docker compose logs -f --tail=50 sentinel-1

5 秒后会看到 +sdown master mymaster,几秒后 +odown(客观下线,说明拿到两票),接着 +try-failover、+elected-leader、+failover-state-send-slaveof-noone,最后 +switch-master mymaster 127.0.0.1 6380 127.0.0.1 6381。

从杀掉进程到完成切换,这个实验里是 8 到 12 秒。这个数字就是你的写入中断窗口,不是”几毫秒”。

客户端侧,用 redis-py 的 Sentinel 连接,让它自己去问:

from redis.sentinel import Sentinel

sentinel = Sentinel(
    [("127.0.0.1", 26380), ("127.0.0.1", 26381), ("127.0.0.1", 26382)],
    socket_timeout=0.5,
    password="Er7pLq2mSx",
    sentinel_kwargs={"password": ""},
)

master = sentinel.master_for("mymaster", db=0)
print(master.set("probe", "1"))
print(sentinel.discover_master("mymaster"))

master_for 返回的不是一条连接,而是一个会在失败时重新问哨兵的代理。不要把它缓存成全局变量再自己拆出 connection pool,那样切换后旧池里的地址还是旧的。

把旧主重新拉起来,它会以从库身份回归,日志里出现 +convert-to-slave。这一步经常被人忽略:重启的旧主不会自动变回主库,除非哨兵再次切换。

7. 三个必然踩到的坑

坑一:哨兵广播的是容器内网 IP。 客户端拿到 172.18.0.4:6380,在宿主机上根本连不上。表现是”哨兵说主库在 6380,客户端连 6380 一直超时”。解法是显式写 sentinel announce-ip 和 announce-port,把对外可达的地址钉死。

坑二:切换成功,但新主拒绝从库。 日志里是 NOAUTH Authentication required 或 master_link_status:down。原因几乎总是新主的 masterauth 没配——它当从库时用不上这一行,被提升为主库后,别的从库来连它就需要。所有实例都写 requirepass + masterauth,是让提升后的节点立刻可用的唯一办法。

坑三:客户端根本不问哨兵。 应用里写死 host=redis-master,靠 DNS 或负载均衡指向主库。哨兵切换完了,应用还在原地重试。哨兵只解决”谁来当主”,不解决”你怎么知道”。要么用哨兵感知的客户端,要么在切换后触发一次配置刷新。

还有一个不算坑但会咬人的参数:min-replicas-to-write 1 配 min-replicas-max-lag 10。它能让主库在”没有健康从库”时拒绝写入,防脑裂丢数据;但网络抖一下,写入就会失败。开不开,取决于你更能接受丢数据还是更能接受写入报错。

8. 验收清单

  • 三个哨兵互认,SENTINEL sentinels mymaster 返回 2 条
  • INFO replication 里从库 master_link_status:up,延迟小于 2 秒
  • 杀主后 15 秒内 discover_master 返回新地址
  • 切换后新主可写、可读、可被从库同步
  • 旧主重启后自动以从库身份回归
  • sentinel.conf 被自动改写,末尾出现 sentinel known-replica 记录

这六条全过,这套哨兵才算能用。只过前三条的,通常是没演练过一次真实恢复。

写在最后

哨兵这套东西的设计思路挺旧:定期 ping、主观下线、客观下线、投票选主。没有共识算法,没有日志复制,靠的是”多数派看得见”这个朴素假设。

它管用,但它的边界很清楚——它保证的是”有人接班”,不是”一条数据都不丢”。异步复制下,主库在挂掉前最后几百毫秒的写入,如果还没传到从库,切换后就真的没了。哨兵不会告诉你这件事,它只会在日志里打一行 +switch-master。

所以真正该问的问题不是”我的哨兵配好了吗”,而是”我能接受丢多少秒的写入”。前一个问题有标准答案,后一个没有。


你那套主从切换,最近一次演练是什么时候?切换窗口是几秒,有没有量过?

0

钢轨为什么留缝:25米一根,40℃温差,和12毫米的账

上一篇

本地跑大模型:4个工具,和3种选错的信号

下一篇

评论 (0)

登录后可发布~
立即登录
暂无评论

admin

当生活给你的全是不如意,那你一定要相信自己的兴趣!
145
文章
0
评论
-11
喜欢
2026 年 10 月
一 二 三 四 五 六 日
 1234
567891011
12131415161718
19202122232425
262728293031  
« 9 月    

近期评论

聚合文章

一座1吉瓦的机房:三代人的电价,和一个不太好接受的推论
火星甲烷之争:一台车测到21ppb,一颗卫星连0.05都没看到
修表师傅把表推回来:一块表,三次开盖,和一个不修的理由
AI新闻日报 – 2026年10月31日:一张82%的安全考卷,和一次两个月的失守
马桶一天漏500升:一份按收益排序的止漏清单
本地跑大模型:4个工具,和3种选错的信号
用Redis 8搭一主两从自动切换:4份配置,和3个必然踩到的坑
钢轨为什么留缝:25米一根,40℃温差,和12毫米的账

猜你喜欢

用 SQLite 当生产数据库:WAL 模式、并发上限与备份策略的完整配置

用 SQLite 当生产数据库:WAL 模式、并发上限与备份策略的完整配置

admin
14 0 0
如何用Docker在10分钟内搭建个人开发环境

如何用Docker在10分钟内搭建个人开发环境

admin
98 0 0
用 Caddy 2 做反向代理与自动 HTTPS:一份可复现的配置手册

用 Caddy 2 做反向代理与自动 HTTPS:一份可复现的配置手册

admin
22 0 0
普通人如何用AI赚钱?2025最全实操指南

普通人如何用AI赚钱?2025最全实操指南

admin
50 0 0

关于我们

你是否对浩瀚的宇宙充满好奇?你是否渴望掌握未来科技的力量?现在,机会来了!“未来星球”将带你进入奇妙世界,开启你的科技探险之旅! 这是一个充满想象和创造力的博客!

分类导航

首页 新闻资讯 技术教程 软件工具 知识百科 生活实用 个人随笔 生命外星人

友情链接

未来星球AI工具【网络版】 未来星球 pycharm官方站【中国】
Copyright © 2026 未来星球. Designed by nicetheme. 蒙ICP备2026002569号-1
  • 请到 [后台->外观->菜单] 中设置菜单
  • AI未来
  • 生活百科
  • 档案
  • 外星人
  • 未来星球

admin

当生活给你的全是不如意,那你一定要相信自己的兴趣!
145
文章
0
评论
-11
喜欢