Redis进阶——哨兵模式 :命令演示详解
前言主从复制模式虽然能够负载均衡,减轻主机压力,但配置过程中需要注意:一旦主机挂载过多的从节点,当主机故障重启后,多个从节点同时发起复制,导致复制风暴全量复制会触发bgsave,主节点首先需要fork子进程将当前数据保存到RDB文件中,然后再将RDB文件通过网络传输到从节点,那么就会产生2个问题:fork的过程主节点是阻塞的如果主节点在fork子进程+保存RDB文件时耗时过多,可能会导致从节点长时
前言
主从复制模式虽然能够负载均衡,减轻主机压力,但配置过程中需要注意:一旦主机挂载过多的从节点,当主机故障重启后,多个从节点同时发起复制,导致复制风暴
全量复制会触发bgsave,主节点首先需要fork子进程将当前数据保存到RDB文件中,然后再将RDB文件通过网络传输到从节点,那么就会产生2个问题:
- fork的过程主节点是阻塞的
- 如果主节点在fork子进程+保存RDB文件时耗时过多,可能会导致从节点长时间收不到数据而触发超时;此时从节点会重连主节点,然后再次全量复制,再次超时.. 造成循环
✧ 解决办法
避免主机挂载太多从机,我们可以将主节点均匀的分布到不同的主机上,例主-从-从,主-从-从-从或者是更多,例如下图:
▎主-从-从模式
集群具体搭建,可翻阅我之前的文章:Redis进阶——主从复制:命令演示搭建
假设当前的模式为:一主 (6379) 二从 (6380、6381),我们可以通过 info replication 命令查看各客户端的主从复制信息:
✧ 说明:修改配置文件的参数 replicaof <masterip> <masterport> 来配置一主二从模式,配置完需重启服务器,重新连接各客户端才会生效。优点:永久生效,重启服务无需再配置。
☁ 思考:每次都要修改配置文件,再重启服务器,如果集群过多,操作起来也更复杂,重启也会造成短时间服务不可用,那么是否可以直接修改就立即生效,而不用逐个重启?
☆ 不重启:命令模式
- 优点:配置立即生效,无需重启Redis服务
- 缺点:只针对当前有效,如果服务器意外宕机,那么又需要手动配置!
参数示例:
# 需要挂载的主机IP、主机端口号
slaveof <masterhost> <masterport>
目前80、81两个从机挂载在79主机下,我们将其81从机挂载到80从机下,如下:
设置完毕,info replication 命令查看各个客户端节点信息变化:6379—>6380—>6381
☛ 从机晋升主机
假设主机发生意外宕机了,Redis 将无法响应来自客户端的所有写请求,只能接收读请求,因为从机是正常运行的,如果能够在第一时间知晓故障并立刻重启主机,造成的影响只是花费在重启时间长短上,如果无法短时间内重启主机服务,该如何降低生产环境上的影响呢?
朝谋篡位
如果主机断开连接了,我们可以使用 slaveof no one 命令让当前从机变成主机,其他的节点就可以手动连接到最新的这个主节点,如果这个时候原本的主机修复了,就重新连接
操作:模拟主机宕机,从机晋升为主机
现在是 主-从-从模式(6379—>6380—>6381)此时我们模拟主机宕机:
slaveof no one -- 从机关闭复制功能,并由从机 转变成主机
从机成为主机后,如果此时原6379主机重新连接呢? 我们查看各端口的节点关系:
6379—> 6380 —> 6381模式,81 原本就是挂载到80 从机下,即便80由从机升级为主机,也不会影响原本的挂载关系,79主机宕机恢复连接后,master角色不变化,但底下的从机数量为0,因为我们手动修改了配置,将从机修改为主机!
☁ 思考:手动配置从机转变主机,取决于第一时间发现主机宕机,如果第一时间发现不了呢?如何降低生产环境服务器不可用的影响?
哨兵机制(Redis Sentinel)
Redis 2.8版本开始引入。哨兵的核心功能是主节点的自动故障转移。
谋朝篡位的自动版,能够后台监控主机是否故障,从而实现 Master 和 Slave 服务器的切换!
▶ Sentinel (哨兵) 实现了什么功能呢?
- 监控 (Monitoring):哨兵节点会不断地检查Redis节点、其余哨兵节点是否可达。
- 自动故障转移 (Automatic failover):当Redis主节点不能正常工作时,开始自动故障转移操作,将某一个从节点升级为新的主节点,并让其他从节点改为复制新的主节点。
- 配置提供者 (Configuration provider):客户端在初始化时,通过连接哨兵来获得当前Redis服务的主节点地址。
- 通知 (Notification):哨兵节点会将故障转移的结果发送给客户端。
其中,监控和自动故障转移功能,使得哨兵可以及时发现主节点故障并完成转移;而配置提供者和通知功能,则需要在与客户端的交互中才能体现。
▶ 图解说明
哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,独立运行,其原理是哨兵通过发送命令,等待Redis服务器响应,通过判断Redis服务器是否实时回应,判断其状态是否正常运行,从而监控运行的多个Redis实例
上面的哨兵有2个作用:
- 通过发送命令,让Redis服务器回应返回结果,监控其运行状态,包括主服务器和从服务器
- 当哨兵检测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机
★ 哨兵集群
一个哨兵节点对Redis服务器进行监控,可能会出现问题,为此我们可以使用多个哨兵进行监控,各个哨兵之间还会进行监控,形成多哨兵模式,如下图:
✧ 解析: 假设哨兵1先检测到主服务器宕机,系统不会马上进行failover (故障转移) 过程,仅仅是哨兵1主观认为主服务器不可用——主观下线 当哨兵2、3也检测到服务器不可用,并且数量达到一定值时,哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover操作。切换成功后通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线
- 主观下线:任何一个哨兵都是可以监控探测,并作出Redis节点下线的判断;
- 客观下线:有哨兵集群共同决定Redis节点是否下线;
多个 Sentinel (哨兵)节点对Redis主机的故障达成一致,会选举出其中一个Sentinel (哨兵)节点作为领导者负责故障转移。
☁ 思考:一个哨兵不是也能监控吗,为什么要用哨兵集群?
- 防止误判:对于节点的故障判断是由多个 Sentinel 节点共同完成。
- 高可靠:即使个别 Sentinel 节点不可用,整个 Sentinel 节点集合依然是健壮的。
☁ 哨兵怎么监控的呢?
✧ 解析:哨兵 2 向主库发送 INFO 命令。主库接收命令后,把从库列表返回给哨兵。然后哨兵根据从库列表中的连接信息,和每个从库建立连接并持续监控(哨兵1和3同等)
▎命令演示搭建哨兵
Sentinel 节点本身就是独立的 Redis 节点,特殊的节点,不存储数据, 只支持部分命令。
✧ 演示流程如下:
- 创建 sentinel.conf 配置文件,配置相关参数
- 启动配置文件
- 模拟主机宕机,观察其他Redis从机变化
- 模拟主机恢复连接,观察各个Redis 节点主从变化
说明:我们现在是 一主 (6379) 二从 (6380、6381) 模式,如下图:
▸ 第一步:创建并修改 sentinel79.conf 文件,配置相关参数
也可以直接在目录下鼠标右键新建文件,我这里就用终端vim命令方式创建演示了!
a. 打开新的一个终端窗口,使用vim命令
b. 配置监控参数
# 配置参数:哨兵sentinel监控的redis主节点的ip port
# Master-name:主节点的名称,自主命名,只能由字母A-z、数字0-9、这三个字符“.-_“组成
# quorum:配置多少个sentinel哨兵统一认为master主节点失联——客观下线
sentinel monitor <master-name> <ip> <port> <quorm>
c. 文件目录所在位置,查看已设置好的配置文件
▸ 第二步:启动配置文件
跟启动redis-server 原理是一样的 ,用 redis-sentinel 启动,然后选择哪个conf 文件
a. 使用 redis-sentinel /usr/local/etc/sentinel79.conf 启动,跟启动redis-server是一样的
▸ 第三步:模拟6379主机宕机,观察其他节点变化
a. 断开6379主机连接
b. 查看sentinel 哨兵节点窗口,哨兵监控节点变化如下:
c. 查看6381 主从复制节点信息
由上述操作可知,6379主机意外宕机,哨兵节点监控到后,进行故障转移,选举其中某个slave晋升为master,并将原本挂载在6379主机下的6380从机,也重新 “认6381为老大”。
▸ 第四步:模拟6379主机恢复连接,观察其他Redis节点变化
a. 恢复6379主机连接
b. 查看哨兵节点窗口变化:
c. 查看6381节点信息
☆ 使用小结
如果是哨兵机制,当master主机宕机后,哨兵进行选举投票,并自动尝试进行故障转移操作,选出某个slave从机晋升为主机,然后将挂载到原主机下的从机,全部转移挂载到新master主机下
当主机宕机后,这种自动配置的方式远比于手动配置 slaveof <master-host><master-port> 把当前节点修改为主节点的方式高效,手动配置需要人工干预,费时费力,还会造成一段时间内服务不可用,其次还要手动把挂载原主机下的从机,再手动挂载到新master上。
☆ 需要注意:
- 上述只演示1个sentinel 哨兵节点的配置,也可以配置多个哨兵节点,降低单机哨兵故障率
- 上述配置 sentinel.conf 文件,只配置了一个 sentinel monitor 参数,这一个参数就能实现这么多操作(故障转移,主从切换技术等),其实远不止一个参数,查看更多参数配置请滑至文末
新master是如何选出的?
主从切换技术,主机宕机后,被选举成新master的slave从机,是如何层层选拔的呢?
主要围绕着3点
- 过滤掉不健康的(下线或断线),没有回复过哨兵ping响应的从节点
- 选择 salve-priority从节点优先级最高(redis.conf)的
- 选择复制偏移量最大,指复制最完整的从节点
哨兵集群的如何选举哨兵Leader?
判断完主机下线后,由哪个哨兵节点来执行主从切换呢?
在哨兵集群模式中,发起故障转移 和 通知都只需要一个主的哨兵节点就可以了。
✧ 哨兵的选举机制
Raft选举算法: 选举的票数 >= (sentinel 数)/2+1,将成为领导者,如果没有超过,继续选举
✦ 成为Leader的哨兵,要满足2个条件:
- 第一,拿到半数以上的赞成票;
- 第二,拿到的票数同时还需要 >= 哨兵配置文件中的 quorum 值。
其中quorum值就是上述演示的哨兵节点的创建和配置的sentinel.conf文件参数:
sentinel monitor <master-name> <ip> <port> <quorum>
举例:假设有3个哨兵节点,quorum值设置为2,只要拿到2张赞成票,就能成为Leader哨兵
★ Leader选举流程如下:
- 判断了主观下线的sentinel节点,会向其他的sentinel节点发送命令,要求将它设置成为领导者
- 收到命令的sentinel,如未同意通过其它节点发送的命令,那么就会同意请求,否则就会拒绝
- 如果sentinel节点发现自己票数超过半数,同时也超过了quorun值,就会成为领导者
- 进行故障转移操作
★ 判定客观下线 ≠ 能够主从切换
即便成为了Leader哨兵,也不一定能够执行主从切换技术!
假设 Redis 1主4从,配置了5个哨兵,其中3个哨兵故障,配置quorum值为2,当主库宕机时:
问题一:哨兵能否判断主库“客观下线”?
答:可以,由于quorum=2,当一个哨兵判断主机“主观下线”后,询问另外一个哨兵,也是一样的结果,2个哨兵都判定“主观下线”,达到了quorum的值,即可认定是客观下线!
问题二:能否执行主从切换?
答:不能!哨兵成功标记主机“客观下线”,在选举Leader时,必须拿到半数以上的赞成票才能竞选成功。即 (5/2+1=3票) ,但只有2个哨兵活着,所以无法推举出Leader!就无法执行主从切换!
故障的转移
哨兵Leader选举成功后,如何进行下一步故障转移操作呢?
图解如下:
✦ 说明
- 将slave-1节点从slave升级为master身份
- 将从节点slave-2指向新的主节点slave-1
- 通知客户端主节点已更换
- 如果原master恢复连接,则将原master变成slave,并挂载到新的主节点slave-1下
转换后如图:
哨兵模式数据丢失问题
哨兵集群在发现 master 宕机后会进行故障转移,也就是启动其中一个slave为 master 。在这过程中,可能会导致数据丢失的情况。
▸ 异步复制
master->slave的复制是异步的,可能存在有部分还没来得及复制到slave,master就宕机了,此时这些部分数据就丢失了。
解决:在异步复制的过程当中,通过 min-slaves-max-lag 配置,就可以确保的说,一旦 slave 复制数据和 ack 延迟时间太长,就认为可能 master 宕机,则master就拒绝写请求,从而降低master宕机时由于部分数据未同步到 slave导致的数据丢失
min-slaves-max-lag 10 要求至少有1个slave,数据复制和同步的延迟不能超过10秒
▸ 集群脑裂
某个master所在机器突然脱离了正常网络,跟其它slave不能连接,但实际上master还运行着。client 还没来得及切换成新的master ,继续写向旧的 master 的数据可能丢失,通过 min-slaves-to-write 确保必须是有多少个从 节点连接,并且延迟时间小于 min-slaves-max-lag 多少秒。
min-slaves-to-write [数量] 确保必须是有多少个从 节点连接
附带 sentinel.conf 配置文件参数说明:
# Example sentinel.conf
# Sentinel哨兵实例运行的端口
# 注意:如果配置哨兵集群,端口号要不一样,跟演示中的redis79.conf、redis80.conf 文件同理
port 26379
# 绑定IP地址
# bind 127.0.0.1 192.168.1.1
# 保护模式(是否禁止外部链接,除绑定的ip地址外)
# protected-mode no
# 是否开启守护进程模式
daemonize no
# 启用守护进程运行后,Redis将在/var/run/redis-sentinel.pid中写入一个pid文件
pidfile /var/run/redis-sentinel.pid
# 指定日志文件名。
logfile ""
# 哨兵Sentinel的工作目录
dir /tmp
# 哨兵sentinel监控的主节点的ip和port
# master-name:自主命名主节点名称 注意:只能由 A-z 0-9 和这三个字符 ".-_"组成
# quorum:至少多少个sentinel哨兵统一认为master主节点失联,才判断客观下线
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127.0.0.1 6379 2
# 设置连接master和slave时的密码,如果redis配置了密码,必须配置认证,否则不能自动切换
# 注意:sentinel不能分别为master和slave设置不同的密码,因此master和slave的密码应设置一样
# sentinel auth-pass <master-name> <password>
# 指定多少毫秒后,主节点没有应答哨兵sentinel,此兵主观上认为主节点 s_down,默认30秒
# sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds mymaster 30000
# 指定在发生failover故障转移期间,主备切换时最多可以有多少个slave同时对新master进行同步
# 数字越小:完成failover所需的时间越长,
# 数字越大:意味越多的slave因为replication而不可用
# 可以将这个值设为1,来保证每次只要有个slave处于不能处理命令请求的状态
# sentinel parallel-syncs <master-name> <numreplicas>
#sentinel parallel-syncs mymaster 1
# 指定故障转移超时(以毫秒为单位)。 failover-timeout 可以用在以下这些方面:
# 1. 同一个sentinel对同一个master两次failover之间的间隔时间
# 2. 当一个slave从一个错误的master那里同步数据开始计算时间。
# 直到slave被纠正为向正确的master那里同步数据时。
# 3. 取消正在进行的failover但未生成任何配置更改的故障转移所需的时间
# 4. 当进行failover时,配置所有slaves指向新的master所需的最大时间。
# 即使过了这个超时,slaves依然会被正确配置为指向master。
#
# sentinel failover-timeout <master-name> <milliseconds> 默认3分钟
sentinel failover-timeout mymaster 180000
############################# 脚本执行 ####################################
# 用于配置所需要执行的脚本,例如可以通过脚本来发送邮件通知管理员系统运行故障
# 对于脚本的运行结果有以下规则:
# 1. 执行后返回1:则该脚本稍后将会被再次执行(最多重试次数为当前设置的10次)。
# 2. 执行后返回2或更高的值:则不会重试执行。
# 注意:如果脚本执行过程中因为收到信号而终止执行,则同返回值为1时的行为相同
#
# 一个脚本的最大执行时间为60s,如果超过此时间,脚本会被一个sigkill信号终止,之后重新执行
# 通知脚本
#
# 1. 当sentinel有任何警告级别的事件发生时(例如-sdown主观下线,-odown客观下线等)将调用该脚本
# 此脚本应通过电子邮件,SMS或任何其他消息传递系统通知系统管理员 监控的Redis系统出了问题。
#
# 2. 使用两个参数调用脚本:第一个是事件类型,第二个是事件描述。
#
# 3. 如果sentinel.conf配置文件中配置了这个脚本路径
# 那么必须保证这个脚本存在于这个路径,并且是可执行的,否则sentinel无法正常启动成功。
#
# sentinel notification-script <master-name> <script-path> 举例:
#
# sentinel notification-script mymaster /var/redis/notify.sh
# 客户重新配置脚本
# 当主机因failover故障转移而发生改变时,脚本将被调用,通知相关客户端关于master地址已改变的信息
#
# 以下参数将会在调用脚本时传给脚本:
# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
# 1. <state> 目前始终是故障转移 "failover"
# 2. <role> 是 "leader" 或 "observer" 中的一个
#
# from-ip, from-port, to-ip, to-port 用来和旧的master和 新的master(即旧的slave)通信
# 这个脚本应该是通用的,能被多次调用,不是针对性的
#
# sentinel client-reconfig-script <master-name> <script-path> 举例:
# sentinel client-reconfig-script mymaster /var/redis/reconfig.sh
更多推荐
所有评论(0)