Redis 哨兵 Sentinel
Redis 哨兵 Sentinel
主从架构和MySQL的主从复制一样,无法实现master和slave角色的自动切换,即当master出现故障时, 不能实现自动的将一个slave节点提升为新的master节点,即主从复制无法实现自动的故障转移功能,如果想实现转移,则需要手动修改配置,才能将 slave 服务器提升新的master节点.此外只有一个主节点支持写操作,所以业务量很大时会导致Redis服务性能达到瓶颈
需要解决的主从复制以下存在的问题:
- master和slave角色的自动切换,且不能影响业务
- 提升Redis服务整体性能,支持更高并发访问
1. 哨兵 Sentinel 工作原理
生产环境如果要使用此功能建议使用Redis的2.8版本以上版本
Sentinel 故障转移
- 多个sentinel发现并确认master有问题。
- 选举出一个sentinel作为领导。
- 选出一个slave作为master。
- 通知其余slave成为新的master的slave。
- 通知客户端主从变化
- 等待老的master复活成为新master的slave。
专门的Sentinel 服务进程是用于监控redis集群中Master工作的状态,当Master主服务器发生故障的时候,可以实现Master和Slave的角色的自动切换,从而实现系统的高可用性
Sentinel是一个分布式系统,即需要在多个节点上各自同时运行一个sentinel进程,Sentienl 进程通过流言协议(gossip protocols)来接收关于Master是否下线状态,并使用投票协议(Agreement Protocols)来决定是否执行自动故障转移,并选择合适的Slave作为新的Master
每个Sentinel进程会向其它Sentinel、Master、Slave定时发送消息,来确认对方是否存活,如果发现某个节点在指定配置时间内未得到响应,则会认为此节点已离线,即为主观宕机Subjective Down,简称为 SDOWN
如果哨兵集群中的多数Sentinel进程认为Master存在SDOWN,共同利用 is-master-down-by-addr 命令,互相通知后,则认为客观宕机Objectively Down, 简称 ODOWN
接下来利用投票算法,从所有slave节点中,选一台合适的slave将之提升为新Master节点,然后自动修改其它slave相关配置,指向新的master节点,最终实现故障转移failover
Redis Sentinel中的Sentinel节点个数应该为大于等于3且最好为奇数
客户端初始化时连接的是Sentinel节点集合,不再是具体的Redis节点,即 Sentinel只是配置中心不是代理。
Redis Sentinel 节点与普通 Redis 没有区别,要实现读写分离依赖于客户端程序
Sentinel 机制类似于MySQL中的MHA功能,只解决master和slave角色的自动故障转移问题,但单个 Master 的性能瓶颈问题并没有解决
Redis 3.0 之前版本中,生产环境一般使用哨兵模式较多,Redis 3.0后推出Redis cluster功能,可以支持更大规模的高并发环境
Sentinel中的三个定时任务
每10 秒每个sentinel 对master和slave执行info
发现slave节点
确认主从关系
每2秒每个sentinel通过master节点的channel交换信息(pub/sub)
通过sentinel__:hello频道交互
交互对节点的“看法”和自身信息
每1秒每个sentinel对其他sentinel和redis执行ping
2. 实现哨兵架构与具体搭建步骤
哨兵需要先实现主从复制
哨兵的前提是已经实现了Redis的主从复制
注意: master 的配置文件中masterauth 和 slave 都必须相同
2.1 准备主从复制环境配置
先通过一键编译脚本在三台主机上安装好redis,搭建一主两从
主机IP | 节点 |
---|---|
10.0.0.100 | 主 |
10.0.0.101 | 从 |
10.0.0.102 | 从 |
# 修改所有主从节点配置文件
[root@ubuntu2204 ~]#vim /apps/redis/etc/redis.conf
bind 0.0.0.0
masterauth 123456
requirepass 123456
# 修改所有从节点配置文件
[root@ubuntu2204 ~]#vim /apps/redis/etc/redis.conf
replicaof 10.0.0.100 6379
# 所有主从节点执行 重启redis服务
[root@ubuntu2204 ~]#systemctl restart redis
# 查看主从节点状态
[root@ubuntu2204 ~]#redis-cli -a 123456 info replication
2.2 编辑哨兵配置
sentinel 配置
Sentinel实际上是一个特殊的redis服务器,有些redis指令支持,但很多指令并不支持.默认监听在 26379/tcp端口.
哨兵服务可以和Redis服务器分开部署在不同主机,但为了节约成本一般会部署在一起
所有redis节点使用相同的以下示例的配置文件
# 在源码目录有sentinel.conf,复制到安装目录即可
[root@ubuntu2204 ~]#cp /usr/local/src/redis-7.2.6/sentinel.conf /apps/redis/etc/
[root@ubuntu2204 ~]#ll /apps/redis/etc/
[root@ubuntu2204 ~]#chown redis.redis /apps/redis/etc/sentinel.conf
[root@ubuntu2204 ~]#ll /apps/redis/etc/
# 修改配置文件
[root@ubuntu2204 ~]#vim /apps/redis/etc/sentinel.conf
protected-mode no
port 26379
daemonize no
pidfile /apps/redis/run/redis-sentinel.pid
logfile "/apps/redis/log/redis-sentinel.log"
dir /apps/redis/data/sentinel
#mymaster是集群的名称,此行指定当前mymaster集群中master服务器的地址和端口
#2为法定人数限制(quorum),即有几个sentinel认为master down了就进行故障转移,一般此值是所有sentinel节点(一般总数是>=3的 奇数,如:3,5,7等)的一半以上的整数值,比如,总数是3,即3/2=1.5,取整为2,是master的ODOWN客观下线的依据
sentinel monitor mymaster 10.0.0.100 6379 2
# mymaster集群中master的密码,注意此行要在上面行的下面
sentinel auth-pass mymaster 123456
# 判断mymaster集群中所有节点的主观下线(SDOWN)的时间,单位:毫秒,建议3000
sentinel down-after-milliseconds mymaster 3000
# #发生故障转移后,可以同时向新master同步数据的slave的数量,数字越小总同步时间越长,但可以减轻新master的负载压力
sentinel parallel-syncs mymaster 1
# 所有slaves指向新的master所需的超时时间,单位:毫秒
sentinel failover-timeout mymaster 180000
acllog-max-len 128
# 禁止修改脚本
sentinel deny-scripts-reconfig yes
SENTINEL resolve-hostnames no
SENTINEL announce-hostnames no
# 修改一个节点,其他节点直接scp
[root@ubuntu2204 ~]#scp /apps/redis/etc/sentinel.conf 10.0.0.101:/apps/redis/etc/
[root@ubuntu2204 ~]#scp /apps/redis/etc/sentinel.conf 10.0.0.102:/apps/redis/etc/
# 修改scp后的两个sentinel.conf文件的权限
[root@ubuntu2204 ~]#chown redis.redis /apps/redis/etc/sentinel.conf
# 验证三个哨兵服务器的配置
[root@ubuntu2204 ~]#grep -Ev '^#|^$' /apps/redis/etc/sentinel.conf
protected-mode no
port 26379
daemonize no
pidfile /apps/redis/run/redis-sentinel.pid
loglevel notice
logfile "/apps/redis/log/redis-sentinel.log"
dir /apps/redis/data/sentinel
sentinel monitor mymaster 10.0.0.100 6379 2
sentinel auth-pass mymaster 123456
sentinel down-after-milliseconds mymaster 30000
acllog-max-len 128
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes
SENTINEL resolve-hostnames no
SENTINEL announce-hostnames no
SENTINEL master-reboot-down-after-period mymaster 0
2.3 启动哨兵服务
# 生成service文件
[root@ubuntu2204 ~]#vim /lib/systemd/system/redis-sentinel.service
[Unit]
Description=Redis Sentinel
After=network.target
[Service]
ExecStart=/apps/redis/bin/redis-sentinel /apps/redis/etc/sentinel.conf --supervised systemd
ExecStop=/bin/kill -s QUIT $MAINPID
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
[root@ubuntu2204 ~]#systemctl daemon-reload
[root@ubuntu2204 ~]#systemctl enable --now redis-sentinel.service
[root@ubuntu2204 ~]#systemctl status redis-sentinel.service
注意:
1. 确保权限是redis
2. Redis Sentinel 配置 daemonize yes 与 --supervised systemd 冲突,导致 systemd 无法管理服务进程,应将 daemonize 改为 no
3. --supervised systemd:表示 Redis Sentinel 由 systemd 管理进程生命周期,Redis 不能自己后台运行
2.4 验证哨兵服务
# 查看哨兵服务端口状态
[root@ubuntu2204 run]#ss -nlt
# 查看哨兵日志
[root@ubuntu2204 ~]#tail -f /apps/redis/log/redis-sentinel.log
# 当前sentinel状态
[root@ubuntu2204 ~]#redis-cli -p 26379 info sentinel
# 在sentinel状态中尤其是最后一行,涉及到masterIP是多少,有几个slave,有几个sentinels,必须是符合全部服务器数量
# 两个slave,三个sentinel服务器,如果sentinels值不符合,检查myid可能冲突
master0:name=mymaster,status=ok,address=10.0.0.100:6379,slaves=2,sentinels=3
# 查看 Redis 各节点状态
[root@ubuntu2204 ~]#redis-cli -a 123456 info replication
2.5 停止 Master 节点实现故障转移
# 停止 Master 节点
[root@ubuntu2204 ~]#systemctl stop redis
# 变成101
[root@ubuntu2204 ~]#redis-cli -p 26379 info sentinel
master0:name=mymaster,status=ok,address=10.0.0.101:6379,slaves=2,sentinels=3
# 故障转移后从节点redis.conf中的replicaof行的master IP会被修改
[root@ubuntu2204 ~]#grep replicaof /apps/redis/etc/redis.conf
# Master-Replica replication. Use replicaof to make a Redis instance a copy of
# replicaof <masterip> <masterport>
replicaof 10.0.0.101 6379
# 哨兵配置文件的sentinel monitor IP 同样也会被修改
[root@ubuntu2204 ~]#grep 'sentinel monitor' /apps/redis/etc/sentinel.conf
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 10.0.0.101 6379 2
# 验证 Redis 各节点状态
[root@ubuntu2204 ~]#redis-cli -a 123456 info replication
[root@ubuntu2204 ~]#redis-cli -p 26379 info sentinel
2.6 原 Master 重新加入 Redis 集群
# 启动redis
[root@ubuntu2204 ~]#systemctl start redis
# 观察状态
[root@ubuntu2204 ~]#grep replicaof /apps/redis/etc/redis.conf
[root@ubuntu2204 ~]#redis-cli -a 123456 info replication
[root@ubuntu2204 ~]#redis-cli -p 26379 info sentinel
3. Sentinel 运维
在Sentinel主机手动触发故障切换
[root@ubuntu2204 ~]#vim /apps/redis/etc/redis.conf
replica-priority 80
# 或者动态修改
[root@ubuntu2204 ~]#redis-cli -a 123456
127.0.0.1:6379> CONFIG GET replica-priority
127.0.0.1:6379> CONFIG SET replica-priority 60
127.0.0.1:6379> CONFIG GET replica-priority
# 原主节点自动变成从节点
[root@ubuntu2204 ~]#redis-cli -p 26379
127.0.0.1:26379> sentinel failover mymaster
OK
127.0.0.1:26379>
4. 应用程序连接 Sentinel
Redis 官方支持多种开发语言的客户端: https://redis.io/clients
4. 1 客户端连接 Sentinel 工作原理
- 客户端获取 Sentinel 节点集合,选举出一个 Sentinel
- 由这个sentinel 通过masterName 获取master节点信息,客户端通过sentinel get-master-addr-by-name master-name这个api来获取对应主节点信息
- 客户端发送role指令确认master的信息,验证当前获取的“主节点”是真正的主节点,这样的目的是为 了防止故障转移期间主节点的变化
- 客户端保持和Sentinel节点集合的联系,即订阅Sentinel节点相关频道,时刻获取关于主节点的相关信息,获取新的master 信息变化,并自动连接新的master