Redis 集群 - Sentinel 模式
Redis哨兵是一个分布式的高可用性解决方案,主要功能包括 :
- 监控 : 持续检查主节点(master)、从节点(slave)的健康状态。
- 自动故障转移 : 当主节点不可用时,自动选举新的主节点并
更新配置. - 通知 : 通过api或脚本通知系统管理员故障事件。
- 配置中心 : 客户端通过哨兵获取当前有效主节点地址。
哨兵核心配置示例
- 哨兵配置文件
redis-sentinel.confport 26379 sentinel monitor mymaster 172.18.0.2 6379 2 sentinel down-after-milliseconds mymaster 5000 sentinel failover-timeout mymaster 10000 sentinel parallel-syncs mymaster 1 # 如果master有密码,需配置,若从节点也设置密码,应当与主节点一致 sentinel auth-pass mymaster basic_master # 故障转移 时出发自定义脚本,如邮件、短信报警 sentinel notification-script mymaster /usr/local/etc/redis/notification.sh
redis 的 master、slave使用相同密码方便管理。
- 参数说明:
mymaster:监控的主节点的别名,redis-master 6379:主节点地址(此处使用docker容器名),也可为具体ip+port2: 法定人数,至少需要半数以上哨兵同意才出发故障转移,当前案例3个哨兵实例,所以用2个法定人数down-after-milliseconds: 判定主节点主观下线的毫秒数。auth-pass:若主节点有密码,需同步配置。notifucation-script: 通知脚本,使用脚本将故障转移情况通知给程序员
docker 部署哨兵集群(3个哨兵实例)
- 创建共享网络(与主从节点相同)
docker network create redis-net -
启动哨兵容器
需启动至少3个哨兵,避免脑裂。docker run -d \ --name redis-sentinel-01 \ --network redis-net \ -p 26379:26379 \ -v path/configs/redis/redis-sentinel.conf:/usr/local/etc/redis/sentinel.conf \ -v path/configs/redis/notification.sh:/usr/local/etc/redis/notification.sh \ redis:latest \ redis-sentinel /usr/local/etc/redis/sentinel.conf docker run -d \ --name redis-sentinel-02 \ --network redis-net \ -p 26380:26379 \ -v path/configs/redis/redis-sentinel.conf:/usr/local/etc/redis/sentinel.conf \ -v path/configs/redis/notification.sh:/usr/local/etc/redis/notification.sh \ redis:latest \ redis-sentinel /usr/local/etc/redis/sentinel.conf docker run -d \ --name redis-sentinel-03 \ --network redis-net \ -p 26381:26379 \ -v path/configs/redis/redis-sentinel.conf:/usr/local/etc/redis/sentinel.conf \ -v path/configs/redis/notification.sh:/usr/local/etc/redis/notification.sh \ redis:latest \ redis-sentinel /usr/local/etc/redis/sentinel.conf
部署可能问题问题
-
指令拼写错误
sentinel moniter 应为 sentinel monitor(拼写错误)。docker logs redis-sentinel-01 *** FATAL CONFIG FILE ERROR (Redis 7.4.0) *** Reading the configuration file, at line 2 >>> 'sentinel moniter mymaster redis-master 6379 2' Unrecognized sentinel configuration statement. -
找不到通知脚本或启动配置
配置文件、通知脚本应挂载到正确位置
sentinel配置中使用通知脚本的路径应当正确 -
Can't resolve instance hostname.
使用主节点容器名,无法访问到。错误原因分析:
-
网络隔离:
哨兵容器 (redis-sentinel-01) 和 Redis 主节点容器 (redis-master) 不在同一个 Docker 网络,
导致哨兵无法通过容器名称 redis-master 解析到主节点的 IP 地址。
在哨兵容器启动时,应使用--network将哨兵与主节点保持在相同docker 网络或者使用其具体ip,使用
docker inspect redis-master见于NetworkSettings.Networks.redis-net.IPAddress得到一个ipip直连存在缺点,其ip可能会变动
-
端口映射冲突:
主节点容器 redis-master 的端口映射为 63790->6379,
跨容器通信时应直接使用容器名称+内部端口,无需依赖宿主机映射端口。
所以应当使用6379
-
补充内容:
- 有时使用主节点的容器名无法正常启动哨兵容器,可修改为主节点的ip,可以使用docker inspect redis-net查看
- 主节点关闭后,哨兵会推举1个从节点成为新的主节点,
- 主节点重启后,会默认被分配为从节点,想重新设置为主节点,可将当前主节点stop,哨兵会重新推举主节点,需将主节点的优先级设置高
- 如果主节点发生故障,系统管理员可以将其中一个从节点提升为新的主节点,以确保系统的可用性。
Redis Sentinel可以自动监测主节点的健康状态,并在主节点故障时自动进行故障转移。
哨兵 Sentinel
环境搭建
哨兵是 Redis 的一个分布式集群管理工具,它负责监控主从节点的状态,
当主节点发生故障时,哨兵会自动进行故障转移,保证服务的可用性。
配置
配置文件名 : redis-sentinel.conf
##################################
# Sentinel 基本配置
##################################
# Sentinel 的监听端口,默认为 26379。如果运行多个 Sentinel,可以在不同实例中修改该端口。
# port 26379
# Sentinel 工作目录,用于存储自身的状态文件(sentinel.conf),建议指定一个独立的目录。
dir /tmp
# Sentinel 的日志文件,用于记录运行时的日志信息。
logfile "/var/log/sentinel.log"
##################################
# 监控主节点的配置
##################################
# 监控主节点的配置,格式如下 :
# sentinel monitor <master-name> <ip> <port> <quorum>
# 参数说明 :
# - <master-name>: 主节点名称,可以自定义,但需要在所有 Sentinel 中保持一致
# - <ip>: 主节点的 IP 地址
# - <port>: 主节点的 Redis 服务端口
# - <quorum>: 至少需要多少个 Sentinel 节点认为主节点宕机才能进行故障转移
sentinel monitor mymaster 172.19.0.2 6379 2
# Sentinel 判断主节点或从节点失效的超时时间(毫秒)。在该时间内未收到心跳信号会认为该节点不可用。
sentinel down-after-milliseconds mymaster 5000
# 当执行故障转移时,指定同时可以有多少个从节点与新的主节点进行数据同步。
# 值越大,数据同步会更快,但对新的主节点的负载也更大。
sentinel parallel-syncs mymaster 1
# 故障转移超时时间(毫秒)。指定 Sentinel 允许故障转移完成的最大时间。
# 如果故障转移没有在该时间内完成,Sentinel 会将操作视为失败。
sentinel failover-timeout mymaster 10000
# 如果主节点设置了密码,Sentinel 需要使用密码才能连接到主节点。
# 替换 "yourpassword" 为实际的主节点密码。
# 如果没有设置密码,注释掉这一行即可。
# sentinel auth-pass mymaster yourpassword
##################################
# 从节点配置
##################################
# Sentinel 可以配置将特定从节点排除在故障转移之外。
# 格式为 : sentinel deny-scripts-reconfig mymaster <ip> <port>
# 当从节点不应参与故障转移时,可以使用该配置。
容器运行
docker run -d --name redis-sentinel1 --network redis-net -p 26379:26379 -v ./redis-sentinel.conf:/etc/redis/sentinel.conf redis:latest redis-sentinel /etc/redis/sentinel.conf
docker run -d --name redis-sentinel2 --network redis-net -p 26378:26379 -v ./redis-sentinel.conf:/etc/redis/sentinel.conf redis:latest redis-sentinel /etc/redis/sentinel.conf
docker run -d --name redis-sentinel3 --network redis-net -p 26377:26379 -v ./redis-sentinel.conf:/etc/redis/sentinel.conf redis:latest redis-sentinel /etc/redis/sentinel.conf
常用指令
先进入容器
docker exec -it redis-sentinel1 redis-cli -p 26379
- 查看主节点
SENTINEL get-master-addr-by-name mymaster
> SENTINEL get-master-addr-by-name mymaster
1) "172.19.0.3"
2) "6379"
- 查看所有已知的从节点
SENTINEL slaves mymaster
> SENTINEL slaves mymaster
...一堆从节点内容
- 查看 Sentinel 实例信息
会列出其他的sentinel的实例信息,不会列自己的。
SENTINEL sentinels mymaster
> SENTINEL sentinels mymaster
...一堆其他sentinel信息
关于哨兵数量
-
哨兵数量无需与redis实例数量一致
-
Sentinel 的数量通常需要满足奇数个(例如 3 个或 5 个)
原因是为了避免脑裂
当 Sentinel 执行主节点故障转移时,需要通过投票达成共识,至少有多数(超过半数)的 Sentinel 同意,才能进行故障转移。如果 Sentinel 数量是偶数,容易导致投票无法过半,从而影响故障转移的决策。
现象
- 当主库曾经崩溃过,哨兵发现后会另设一个从库为主库,并记录新主库的ip,在重启前都会以该ip为主库,若再次发生主库崩溃则更新该ip。
- 原redis容器若删除,重启时使用配置规定了主库的ip,且该ip与哨兵记录的ip不同,将在一段时间后,将哨兵记录的ip设为主库,原主库成为从库。
Go 代码示例
一方面如果主库崩溃了,会另设一个从库实例为主库,
另一方面,基于现象中描述的,虽然启动时更具配置设置了一个实例为主库,但是哨兵可能会另设其他实例为主库,
所以不能使用固定ip连接主库,应该使用哨兵提供的api来获取主库的ip,再连接。