9、sentinel哨兵
前言
Redis主从复制下,一旦主节点由于故障不能提供服务需要人工将从节点晋升成主节点,因为代码中可能还是以主节点开发的,需要修改代码修改主节点。同时需要将其他节点的主节点要复制过来,这样肯定是不行,因为需要人工的干预
基本概念
对于Redis许多概念都有不同的名词解释,所以解释Redis Sentinel,Redis高可用实现方案
1、主从复制的问题
1、前言中介绍过
下面这两个属于redis分布式问题
2、主节点写能力受到单机的限制
3、主节点的存储能力受到单机的限制
2、Redis Sentinel高可用
它是一个分布式架构,其中包多个Sentinel节点和Redis数据节点,每个Sentinel节点会对数据节点和其余Sentinel节点进行监控,当它发现节点不可达的时候,会节点做下线标识,如果被标识的是主节点,它还会和其他Sentinel商量,当大部分人为主节点不可用的时候,会选举出一个Sentinel节点用来完成主节点的自动故障转移的工作,同时将这个变化通知给应用方,整个过程是自动的。不需要人工来介入
配置客户端体用这,客户端初始化的时候连接的Sentinel集合从中获取主节点信息,所以才有上面通知应用方,从而获取主节点信息
安装和部署
准备工作:
这里部署3个Sentinel(26379、26380、26381)、1个master(6379)、2个slave(6380、6381)
1、配置主节点
解释:daemonize
daemonize:redis采用的是单进程多线程的模式。当redis.conf中选项daemonize设置成yes时,代表开启守护进程模式。在该模式下,redis会在后台运行,并将进程pid号写入至redis.conf选项pidfile设置的文件中,此时redis将一直运行,除非手动kill该进程。
但当daemonize选项设置成no时,当前界面将进入redis的命令行界面,exit强制退出或者关闭连接工具(putty,xshell等)都会导致redis进程退出。
1、配置
daemonize yes
logfile "6379.log" //也就是说redis-server启动之后的日志放到了dir目录下的6379.log
dbfilename "dump-6379.rdb"
dir "/usr/local/redis/dir"
2、启动
MacBook-Pro:src healerjean$ redis-server ../redis.conf
观察/usr/local/redis/dir 目录下面文件6379.log
5928:M 19 Apr 21:01:18.903 * Increased maximum number of open files to 10032 (it was originally set to 256).
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 3.2.9 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in standalone mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 6379
| `-._ `._ / _.-' | PID: 5928
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
5928:M 19 Apr 21:01:18.907 # Server started, Redis version 3.2.9
5928:M 19 Apr 21:01:18.907 * The server is now ready to accept connections on port 6379
3、测试下主节点是否可用
healerjean$ redis-cli -h 127.0.0.1 -p 6379 ping
PONG
2、启动两个从节点
6580 和 6381 两个从节点一模一样
2.1、配置从节点
redis.conf
daemonize yes
logfile "6380.log"
dbfilename "dump-6380.rdb"
dir "/usr/local/redis/dir"
slaveof 127.0.0.1 6379
daemonize yes
logfile "6381.log"
dbfilename "dump-6381.rdb"
dir "/usr/local/redis/dir"
slaveof 127.0.0.1 6379
2.2、测试从节点是否启动
MacBook-Pro:src healerjean$ redis-cli -h 127.0.0.1 -p 6380 ping
PONG
MacBook-Pro:src healerjean$ redis-cli -h 127.0.0.1 -p 6381 ping
PONG
2.3、确定主从关系
2.3.1、从视角角度
可以看到从节点8081的主节点为6379
127.0.0.1:6381> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:5
master_sync_in_progress:0
slave_repl_offset:435
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6381>
2.3.2、主视角角度
可以明显的看到下面两个从节点
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=547,lag=1
slave1:ip=127.0.0.1,port=6381,state=online,offset=547,lag=0
master_repl_offset:547
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:546
127.0.0.1:6379>
3、部署Sentinel节点
3.1、配置
三个节点的配置完全一致,只不过是端口不同
daemonize yes
logfile "26379.log"
dbfilename "dump-26379.rdb"
dir "/usr/local/redis/dir"
# 2、代表主节点失败至少需要两个sentinel同意
# mymaster为主节点别名 剩下的以后说明
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
3.2、启动Sentinel节点
healerjean$ redis-sentinel ../redis.conf
log文件中
360:X 19 Apr 21:40:23.377 * Increased maximum number of open files to 10032 (it was originally set to 256).
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 3.2.9 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in sentinel mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 26381
| `-._ `._ / _.-' | PID: 6360
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
6360:X 19 Apr 21:40:23.382 # Sentinel ID is b38f8218f0d136dc6f2b18391a88859aafee6a11
6360:X 19 Apr 21:40:23.382 # +monitor master mymaster 127.0.0.1 6379 quorum 2
6360:X 19 Apr 21:40:23.383 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
6360:X 19 Apr 21:40:23.385 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
3.3、查看启动的Sentinel节点信息
可以观察到主节点有一个并且知道了端口号
从节点有2个
Sentinel有3个
info Sentinel
127.0.0.1:26379> info Sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=127.0.0.1:6379,slaves=2,sentinels=3
127.0.0.1:26379>
3、建议
1、生产环境中建议Redis Sentinel的所有节点应该分布在不同的物理机器上
2、配置和优化
1、上面Sentinel中的redis.conf配置如下
daemonize yes
logfile "26379.log"
dbfilename "dump-26379.rdb"
dir "/usr/local/redis/dir"
# 2、代表主节点失败至少需要两个sentinel同意
# mymaster为主节点别名 剩下的以后说明
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
2、其实当我们利用上面的redi.conf启动的时候,就会根据自身监控到的进行修改redi.conf
# 2、代表主节点失败至少需要两个sentinel同意
# mymaster为主节点别名 剩下的以后说明
sentinel myid 3a29be18951c20683dc54c85a79fd8d3eec79ea1
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel config-epoch mymaster 0
sentinel leader-epoch mymaster 0
# Generated by CONFIG REWRITE
sentinel known-slave mymaster 127.0.0.1 6380
sentinel known-slave mymaster 127.0.0.1 6381
sentinel known-sentinel mymaster 127.0.0.1 26381 b38f8218f0d136dc6f2b18391a88859aafee6a11
sentinel known-sentinel mymaster 127.0.0.1 26380 6f3b48dd910ae93566b52f7adfac2a5ef46e52bb
sentinel current-epoch 0
3、Redis安装目录下有个sentinel.conf是默认的Sentinel节点的配置文件,下面开始以它作为例子进行讲解,其实再启动redis.conf的时候,就会将它也进行了修改,只不过没有写入监听信息Generated by CONFIG REWRITE
daemonize yes
logfile "26379.log"
dbfilename "dump-26379.rdb"
dir "/usr/local/redis/dir"
# 2、代表主节点失败至少需要两个sentinel同意
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
1、sentinel monitor
sentinel monitor mymaster 127.0.0.1 6379 2
1、一帮情况下我们将它设置为Sentinel的一半+1,这样就保证绝大多数同意下线标识。
2、还记得上面我们说的领导者吧。至少有max(quorun,num(sentinel)/2)+1)个节点参与选举才可以选出领导者,例如 有5个Sentinle节点,quorun 为4,则为至少需要 max(4,3) = 4 才能进行领导者选举
3、虽然这里没有看到基恩空其余从节点和Sentinel信息,因为他会通过主节点获取有关从及其他节点的信息
2、sentinel down-after-milliseconds mymaster 30000
这个是对节点不可达判断的依据, 每个Sentinel节点定期发送ping命令来判断Redis节点和其他Sentinel节点是否可达,如果超过了这个时间就认为是不可达的,条件太严格有误判风险,宽松则更不好
sentinel down-after-milliseconds mymaster 30000
3、sentinel parallel-syncs mymaster 1
当Sentinel节点集合对主节点故障判断一致的时候,Sentinel领导者节点会做出故障转移操作。选出新的主节点,原来的从节点会向新的主节点发起复制操作,这里的参数则是向新的主节点发起复制操作的从节点个数,配置如果比较大则从节点同时向主节点发起复制操作,但是不好,因为比较拥挤。等于1的时候,则从节点会轮询发起复制
sentinel parallel-syncs mymaster 1
4、sentinel failover-timeout mymaster 180000
故障转移超时时间,,如果第一次失败了,则下次其实超时时间为他的2倍
sentinel failover-timeout mymaster 180000
5、sentinel auth-pass
如果监控的主节点配置了密码,则需要配置主节点的额密码,防止对主节点无法监控
sentinel auth-pass 123456
6、sentinel notification-script mymaster /var/redis/notify.sh
当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等等),将会去调用这个脚本,这时这个脚本应该通过邮件,SMS等方式去通知系统管理员关于系统不正常运行的信息。调用该脚本时,将传给脚本两个参数,一个是事件的类型,一个是事件的描述。如果sentinel.conf配置文件中配置了这个脚本路径,那么必须保证这个脚本存在于这个路径,并且是可执行的,否则sentinel无法正常启动成功。
sentinel notification-script mymaster /var/redis/notify.sh
7、sentinel client-reconfig-script mymaster /var/redis/reconfig.sh
当一个master由于failover故障转移结束的时候,这个脚本将会被调用,通知相关的客户端关于master地址已经发生改变的信息。以下参数将会在调用脚本时传给脚本:
是用来和旧的master和新的master(即旧的slave)通信的。这个脚本应该是通用的,能被多次调用,不是针对性的。
配置示例:
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh
8、也可以监控多个主节点
3、部署技巧
1、Sentinel节点不应该部署在一台物理机上,尽管可能通过虚拟机的方式,造成ip不同但是万一电脑出了故障,所有的Sentinel都会受影响
2、部署至少3个且奇数个数的Sentinel节点,提高准确性
3、合理选择监控多个主节点。比如是监控多个主节点或者是监控一个主节点,如果是监控多个zhu
4、API
Sentinel节点是一个特殊的Redis节点,有自己专属的API,
1、sentinel master
展示所有被监控的主节点的状态已经相关统计信息
有可能监控多个主节点,则展示指定的master则后面加上 mymaster 名字
127.0.0.1:26379> sentinel masters
1) 1) "name"
2) "mymaster"
3) "ip"
4) "127.0.0.1"
5) "port"
6) "6379"
7) "runid"
8) "5b2cb1975b0e2cdbe531e6169dcf5da93fab3524"
9) "flags"
10) "master"
11) "link-pending-commands"
12) "0"
13) "link-refcount"
14) "1"
15) "last-ping-sent"
16) "0"
17) "last-ok-ping-reply"
18) "435"
19) "last-ping-reply"
20) "435"
21) "down-after-milliseconds"
22) "30000"
23) "info-refresh"
24) "4852"
25) "role-reported"
26) "master"
27) "role-reported-time"
28) "350587255"
29) "config-epoch"
30) "0"
31) "num-slaves"
32) "2"
33) "num-other-sentinels"
34) "2"
35) "quorum"
36) "2"
37) "failover-timeout"
38) "180000"
39) "parallel-syncs"
40) "1"
127.0.0.1:26379>
2、sentinel slaves mymaster
展示置顶master主节点相关的从节点信息
127.0.0.1:26379> sentinel slaves mymaster
1) 1) "name"
2) "127.0.0.1:6380"
3) "ip"
4) "127.0.0.1"
5) "port"
6) "6380"
7) "runid"
8) "72702995a478ab9986d5eb6f5e4c05002b97fd92"
9) "flags"
10) "slave"
11) "link-pending-commands"
12) "0"
13) "link-refcount"
14) "1"
15) "last-ping-sent"
16) "0"
17) "last-ok-ping-reply"
18) "250"
19) "last-ping-reply"
20) "250"
21) "down-after-milliseconds"
22) "30000"
23) "info-refresh"
24) "9088"
25) "role-reported"
26) "slave"
27) "role-reported-time"
28) "350691871"
29) "master-link-down-time"
30) "0"
31) "master-link-status"
32) "ok"
33) "master-host"
34) "127.0.0.1"
35) "master-port"
36) "6379"
37) "slave-priority"
38) "100"
39) "slave-repl-offset"
40) "2760782"
2) 1) "name"
2) "127.0.0.1:6381"
3) "ip"
4) "127.0.0.1"
5) "port"
6) "6381"
7) "runid"
8) "d478ed3a435c6995db2dd1b8824bc61c25b30636"
9) "flags"
10) "slave"
11) "link-pending-commands"
12) "0"
13) "link-refcount"
14) "1"
15) "last-ping-sent"
16) "0"
17) "last-ok-ping-reply"
18) "250"
19) "last-ping-reply"
20) "250"
21) "down-after-milliseconds"
22) "30000"
23) "info-refresh"
24) "9088"
25) "role-reported"
26) "slave"
27) "role-reported-time"
28) "350691870"
29) "master-link-down-time"
30) "0"
31) "master-link-status"
32) "ok"
33) "master-host"
34) "127.0.0.1"
35) "master-port"
36) "6379"
37) "slave-priority"
38) "100"
39) "slave-repl-offset"
40) "2760782"
127.0.0.1:26379>
3、展示置顶master的Sentinel集合
127.0.0.1:26379> sentinel sentinels mymaster
1) 1) "name"
2) "b38f8218f0d136dc6f2b18391a88859aafee6a11"
3) "ip"
4) "127.0.0.1"
5) "port"
6) "26381"
7) "runid"
8) "b38f8218f0d136dc6f2b18391a88859aafee6a11"
9) "flags"
10) "sentinel"
11) "link-pending-commands"
12) "0"
13) "link-refcount"
14) "1"
15) "last-ping-sent"
16) "0"
17) "last-ok-ping-reply"
18) "320"
19) "last-ping-reply"
20) "320"
21) "down-after-milliseconds"
22) "30000"
23) "last-hello-message"
24) "1030"
25) "voted-leader"
26) "?"
27) "voted-leader-epoch"
28) "0"
2) 1) "name"
2) "6f3b48dd910ae93566b52f7adfac2a5ef46e52bb"
3) "ip"
4) "127.0.0.1"
5) "port"
6) "26380"
7) "runid"
8) "6f3b48dd910ae93566b52f7adfac2a5ef46e52bb"
9) "flags"
10) "sentinel"
11) "link-pending-commands"
12) "0"
13) "link-refcount"
14) "1"
15) "last-ping-sent"
16) "0"
17) "last-ok-ping-reply"
18) "320"
19) "last-ping-reply"
20) "320"
21) "down-after-milliseconds"
22) "30000"
23) "last-hello-message"
24) "77"
25) "voted-leader"
26) "?"
27) "voted-leader-epoch"
28) "0"
127.0.0.1:26379>
4、sentinel reset mymaster
对当前sentinel节点关于主节点mymaster的配置进行重置,包含清除主节点状态(例如:故障转移),重新发现从节点和主节点
sentinel reset mymaster
5、sentinel failover mymaster
可以说相当有用,对指定主节点进行故障转移,(不商量)当故障转移完成之后,其他sentine按照故障转移结果进行更新自身配置,这个命令在后期运维中非常有用
sentinel failover mymaster
5、实现原理
1、三个定时监控任务
1、每隔10秒,每个Sentinel节点会向主节点和从节点发送info replication命令来获取最新的拓扑结构
作用:
1、用来感知其他新加入的主从节点
2、故障转移之后用来更新拓扑信息
2、每隔2秒会对主节点的频道发送该Sentinel及诶单对于主节点的判断以及当前Sentinel的信息。同时也会订阅该频道,来了解他们各自关于节点的判断
作用:
1、发现新的Sentinel节点并建立连接
1、交换主节点的信息
3、每隔1秒,每隔sentinel节点会向主、从、sentinel及诶单发送ping命令,来确认是不是可达的。
6、主观下线和客观下线
6.1、主观下线
本章之前介绍到,每个Sentinel每隔1秒对主节点、从节点、其他sentinel节点发送ping命令来做心跳检测,当这些超过down-after-millisencondme没有有效回复,则对该节点做失败判定,这个行为就叫做主观下线,那么可以知道这个是当前的sentinel节点的一家之言,有误判的额可能
6.2、客观下线
当判定为的时候,需要和其他的节点进行商量,才会做出下线处理。这个判断就是客观的。
当一个sentinel节点对主节点做主观下线判断后,回、会向其他sentinel节点发送如下命令
SENTINEL is-master-down-by-addr <masterip> <masterport> <sentinel.current_epoch> <runid>
sentinel.current_epoch 当前配置纪元
runid这个参数有两种类型
* 与sentinel节点交换关于主节点下线的判断
当runId 等于当前Sentinel节点的runid时候,是当前sentinel节点希望其他sentinel节点成为领导者的请求
举例;发送如下命令,返回结果会包含三个参数
SENTINEL is-master-down-by-addr 127.0.0.1 6379 0 *
返回结果
down_state 目标sentinel节点对主节点的下线判断,1下线,0在线
leader_runid :当leader_runid等于* 时候、,代表返回结果是用来同意主节点是否不可达,当ledader_runid 等于具体的id代表目标节点同意runid成为领导者
leader_epoch 领导者纪元
6.3、领导者选举
故障转移实际上是一个sentinel节点完成的,所以会进行领导者选举。
1、每个在线的sentinel节点都有资格成为领导者,当他确认主节点主观下线的时候,回向其他节点发送sentinel is-master-down-by-addr 命令要求将自己设置为领导者
2、受到命令的sentinel节点,如果没有同意过其他sentinel节点,将同意它,否则拒绝
3、如果该sentinel节点发送自己得票大于max(quorum,(sentinel)/2+1) 难免他将成为领导者
4、如果没有选出则,将进行下一场选举
7、故障转移
7.1、挑选一个从节点
1、过滤掉不健康的,主观下线,断线,等
2、选择从节点优先级高的slave-proprity,如果存在则返回,不存在则继续
3、选择复制偏移量最大的,存在则返回,不存在则接续
4、选择runid最小的从节点
7.2、将从节点执行slaveof no one命令让他成为主节点
7.3、sentinel会向其它从节点发送命令,让他们成为新主节点的从节点,复制规则和parallel-syncs参数有关
7.4、sentinel结合将原来的主节点更新为从节点,保持它的关注,当其恢复后复制新的主节点信息
8、故障处理
1、节点下线
临时下线
暂时将节点关掉,之后还会重新启动,继续提供服务
永久下线
节点关掉之后不再提供服务,需要做一下清理工作,如删除配置文件,持久化文件,日志文件
主节点下线
在任意一个sentinel节点上执行下面的命令即可,则会自动进行故障转移工作
sentinel fialover mymaseter
从节点和sentinel下线
下线之后sentinel还会对她进行监控,会造成一定的网络资源浪费
7.2、从节点上线
添加方法:只要加上slaveof [masterip] [masteport] 启动即可 (定时监控10秒)
7.3、添加sentinel节点
添加方法同上,也是配置相关信息即可,sentinel会自动发现(定时监控2秒)
7.4、添加主节点
因为主节点不好掌控,如果需要替换则使用命令手动故障转移
sentinel fialover mymaseter
8、高可用
在应用方初始化的时候,连接的的是sentinel集合。那么在客户端的时候应该连接从节点集群。这里后期再解释吧!
如果满意,请打赏博主任意金额,感兴趣的请下方留言吧。可与博主自由讨论哦
支付包 | 微信 | 微信公众号 |
---|---|---|
![]() |
![]() |
![]() |