1.哨兵集群介绍及原理
主从模式,当主节点宕机之后,从节点是可以作为主节点顶上来,继续提供服务的。但是有一个问题,主节点的IP
已经变动了,此时应用服务还是拿着原主节点的地址去访问,此时就需要人工干预进行修改。哨兵恰恰就可以解决这个问题。
访问redis
集群的数据都是通过哨兵集群的,哨兵监控整个redis
集群。一旦发现redis
集群出现了问题,比如主节点挂了,从节点会顶上来。但是主节点地址变了,这时候应用服务无感知,也不用更改访问地址,因为哨兵才是和应用服务做交互的。Sentinel
很好的解决了故障转移,在高可用方面又上升了一个台阶,当然Sentinel
还有其他功能。比如 主节点存活检测、主从运行情况检测、主从切换。Redis
的Sentinel
最小配置是 一主一从。
1.1.redis
哨兵模式原理
哨兵模式建立在主从复制基础之上,会在每一个redis
节点上打开一个sentinel
监控,每个sentinel
进程都有自己的端口号和IP
,所有sentinel
共享集群信息,集群中所有的sentinel
都是可以通信的,当主库宕机后,主库上的sentinel
就会向集群中的其他节点的sentinel
发送信息说主库宕机了,需要在从库上选举master
,这时每个节点上的sentinel
会比较自己redis
配置的ID
号,比如slave1
的ID
号大,slave1
就会选举为master
作为主库,当故障的主库重新加入集群后,主库上的sentinel
会向其他节点的sentinel
询问谁是主库,这时slave1
上的sentinel
就会告诉主库上的sentinel
说slave1
是主库,重新加入集群的主库就会找slave1
同步数据,如果重新加入的主库想再次成为主库,只需要执行提权命令就可以重新成为主库。
主从复制的时候程序配置redis
地址的时候都是写死主库的地址,每次主库宕机都需要手动修改应用。
有了哨兵模式后,在程序代码中配置不是redis
地址,而是配置的所有哨兵的地址,形成一个地址池,即使集群中一个哨兵坏掉了,还有其他两个哨兵,每次需要找redis
写入数据时,程序首先会找哨兵进程,哨兵之间信息共享,会立马告诉程序谁是主库,这时程序拿到哨兵告诉它的redis
主库地址,就会去找主库存数据,因此即使主库坏了,也不需要修改程序代码。
哨兵的配置文件在启动哨兵服务后,尽量不要去修改,因为哨兵会自动增加配置。
哨兵集群个数建议是奇数,比如3/5/7。
配置了哨兵后,当主库挂掉,哨兵选举了新库,会自动把配置文件修改为最新主库的地址。
1.2.哨兵的选举规则
首选判断slave-priority
权重优先级,谁的高谁当选为master
主库,如果都一致,那么久比较各个节点的id
,谁的大谁当选。
1.3.哨兵模式监控的原理
-
每个
Sentinel
以每秒钟一次的频率,向它所有的主服务器、从服务器以及其他Sentinel
实例 发送一个PING
命令。 -
如果一个实例(
instance
)距离最后一次有效回复PING
命令的时间超过down-after-milliseconds
所指定的值,那么这个实例会被Sentinel
标记为主观下线。 -
如果一个主服务器被标记为主观下线,那么正在监视这个主服务器的所有
Sentinel
节点,要以每秒一次的频率确认该主服务器是否的确进入了主观下线状态。 -
如果一个主服务器被标记为主观下线,并且有足够数量的
Sentinel
(至少要达到配置文件指定的数量)在指定的时间范围内同意这一判断,那么这个该主服务器被标记为客观下线。
在一般情况下, 每个Sentinel
会以每 10秒一次的频率,向它已知的所有主服务器和从服务器发送INFO
命令。当一个主服务器被Sentinel
标记为客观下线时,Sentinel
向下线主服务器的所有从服务器发送INFO
命令的频率,会从10秒一次改为 每秒一次。Sentinel
和其他Sentinel
协商主节点的状态,如果主节点处于SDOWN
状态,则投票自动选出新的主节点。将剩余的从节点指向新的主节点进行数据复制。
当没有足够数量的Sentinel
同意主服务器下线时,主服务器的客观下线状态就会被移除。当主服务器重新向Sentinel
的PING
命令返回 有效回复 时,主服务器的主观下线状态就会被移除。
2.搭建哨兵集群
2.1.集群结构
这里我们搭建一个三节点形成的Sentinel
集群,来监管之前的Redis
主从集群。如图:
三个sentinel
实例信息如下:
节点 | IP | PORT |
---|---|---|
s1 | 192.168.150.101 | 27001 |
s2 | 192.168.150.101 | 27002 |
s3 | 192.168.150.101 | 27003 |
2.2.准备实例和配置
要在同一台虚拟机开启3个实例,必须准备三份不同的配置文件和目录,配置文件所在目录也就是工作目录。
我们创建三个文件夹,名字分别叫s1
、s2
、s3
:
# 进入/tmp目录
cd /tmp
# 创建目录
mkdir s1 s2 s3
如图:
然后我们在s1
目录创建一个sentinel.conf
文件,添加下面的内容:
# 哨兵sentinel实例运行的端口
port 27001
# 明确指定哨兵的ip
sentinel announce-ip 10.0.4.10
# 哨兵模式是否后台启动,默认no,改为yes
daemonize yes
# log日志保存位置
logfile /usr/local/redis/sentinel/redis-sentinel.log
###核心配置
# 核心配置。
# 第三个参数:哨兵名字,可自行修改。(若修改了,那后面涉及到的都得同步)
# 第四个参数:master主机ip地址
# 第五个参数:redis端口号
# 第六个参数:哨兵的数量。比如2表示,当至少有2个哨兵发现master的redis挂了,
# 那么就将此master标记为宕机节点。
# 这个时候就会进行故障的转移,将其中的一个从节点变为master
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 10.0.4.10 7001 2
# 当在Redis实例中开启了requirepass foobared 授权密码 这样所有连接Redis实例的客户端都要提供密码
# 设置哨兵sentinel 连接主从的密码 注意必须为主从设置一样的验证密码
# sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster 123456
# 指定多少毫秒之后 主节点没有应答哨兵sentinel 此时 哨兵主观上认为主节点下线 默认30秒
# sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds mymaster 5000
# 这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行同步,这个数字越小,完成failover所需的时间就越长,但是如果这个数字越大,就意味着越多的slave因为replication而不可用。
# 可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。
# sentinel parallel-syncs <master-name> <numslaves>
sentinel parallel-syncs mymaster 1
# 主备切换的时间,若在3分钟内没有切换成功,换另一个从节点切换
# sentinel failover-timeout <master-name> <milliseconds>
sentinel failover-timeout mymaster 60000
# 哨兵sentinel的工作目录
dir "/home/redis/s1"
然后将s1/sentinel.conf
文件拷贝到s2
、s3
两个目录中(在/home
目录执行下列命令):
# 方式一:逐个拷贝
cp s1/sentinel.conf s2
cp s1/sentinel.conf s3
# 方式二:管道组合命令,一键拷贝
echo s2 s3 | xargs -t -n 1 cp s1/sentinel.conf
修改s2
、s3
两个文件夹内的配置文件,将端口分别修改为27002、27003:
sed -i -e 's/27001/27002/g' -e 's/s1/s2/g' s2/sentinel.conf
sed -i -e 's/27001/27003/g' -e 's/s1/s3/g' s3/sentinel.conf
2.3.启动
为了方便查看日志,我们打开3个ssh
窗口,分别启动3个redis
实例,启动命令:
# 第1个
redis-sentinel s1/sentinel.conf
# 第2个
redis-sentinel s2/sentinel.conf
# 第3个
redis-sentinel s3/sentinel.conf
启动后:
2.4.测试
尝试让master
节点7001宕机,查看sentinel
日志:
日志解读:
@
字符之后的内容用于指定主服务器, 这些内容是可选的, 它们仅在 @
字符之前的内容指定的实例不是主服务器时使用。
+reset-master <instance details>
:主服务器已被重置。+slave <instance details>
:一个新的从服务器已经被Sentinel
识别并关联。+failover-state-reconf-slaves <instance details>
:故障转移状态切换到了reconf-slaves
状态。+failover-detected <instance details>
:另一个Sentinel
开始了一次故障转移操作,或者一个从服务器转换成了主服务器。+slave-reconf-sent <instance details>
:领头(leader
)的Sentinel
向实例发送了SLAVEOF host port
命令,为实例设置新的主服务器。+slave-reconf-inprog <instance details>
:实例正在将自己设置为指定主服务器的从服务器,但相应的同步过程仍未完成。+slave-reconf-done <instance details>
:从服务器已经成功完成对新主服务器的同步。-dup-sentinel <instance details>
:对给定主服务器进行监视的一个或多个Sentinel
已经因为重复出现而被移除 —— 当Sentinel
实例重启的时候,就会出现这种情况。+sentinel <instance details>
:一个监视给定主服务器的新Sentinel
已经被识别并添加。+sdown <instance details>
:给定的实例现在处于主观下线状态。-sdown <instance details>
:给定的实例已经不再处于主观下线状态。+odown <instance details>
:给定的实例现在处于客观下线状态。-odown <instance details>
:给定的实例已经不再处于客观下线状态。+new-epoch <instance details>
:当前的纪元(epoch
)已经被更新。+try-failover <instance details>
:一个新的故障迁移操作正在执行中,等待被大多数Sentinel
选中(waiting to be elected by the majority
)。+elected-leader <instance details>
:赢得指定纪元的选举,可以进行故障迁移操作了。+failover-state-select-slave <instance details>
:故障转移操作现在处于select-slave
状态 ——Sentinel
正在寻找可以升级为主服务器的从服务器。no-good-slave <instance details>
:Sentinel
操作未能找到适合进行升级的从服务器。Sentinel
会在一段时间之后再次尝试寻找合适的从服务器来进行升级,又或者直接放弃执行故障转移操作。selected-slave <instance details>
:Sentinel
顺利找到适合进行升级的从服务器。failover-state-send-slaveof-noone <instance details>
:Sentinel
正在将指定的从服务器升级为主服务器,等待升级功能完成。failover-end-for-timeout <instance details>
:故障转移因为超时而中止,不过最终所有从服务器都会开始复制新的主服务器(slaves will eventually be configured to replicate with the new master anyway
)。failover-end <instance details>
:故障转移操作顺利完成。所有从服务器都开始复制新的主服务器了。+switch-master <master name> <oldip> <oldport> <newip> <newport>
:配置变更,主服务器的IP
和地址已经改变。 这是绝大多数外部用户都关心的信息。+tilt
:进入tilt
模式。-tilt
:退出tilt
模式。
查看7002的日志:
查看7003的日志: