1. Redis Sentinel 架构搭建
我们使用经典的一主二从 + 3个sentinel节点来搭建Redis Sentinel 架构。架构图如下:
搭建步骤如下:
(1) 复制配置文件
把$REDIS_HOME/redis.conf
复制为redis_6379.conf
,$REDIS_HOME/sentinel.conf
复制为sentinel_26379.conf
,这样做的原因有两个:
- 保留一份原来的配置文件做备份
- 命名中包括端口号可以很方便的知道使用这个配置文件将会占用哪个端口
[hadoop@node01 redis-4.0.12]$ cp redis.conf redis_6379.conf
[hadoop@node01 redis-4.0.12]$ cp sentinel.conf sentinel_26379.conf
其他两个节点也执行以上操作。
(2) master redis.conf 配置
修改 master 节点的 redis_6379.conf,以下列出的修改过的或者相关的需要了解的配置,没有列出的保持默认即可。
#################### 基础配置 #####################
# 服务是否后台运行
daemonize yes
# 端口号
port 6379
# 日志文件存放位置
logfile /home/hadoop/logs/redis/6379/redis_6379.log
# pid 文件存放位置
pidfile /home/hadoop/pid/redis/6379/redis_6379.pid
# 持久化文件(AOF/RDB)存放位置
dir /home/hadoop/data/redis/6379
#################### RDB 相关 #####################
# RDB文件的名称
dbfilename dump.rdb
# 生成RDB文件的策略
save 900 1
save 300 10
save 60 10000
# RDB文件是否压缩
rdbcompression yes
# 在写入文件和读取文件时是否开启rdb文件检查,检查是否有损坏
rdbchecksum yes
#################### AOF 相关 #####################
# 开启AOF持久化机制
appendonly yes
# AOF文件的名称
appendfilename "appendonly.aof"
# 写AOF文件的策略
appendfsync everysec
# AOF文件重写策略
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# 同时在执行 bgrewriteaof 操作和主进程写aof文件的操作时,两者都会操作磁盘
# 而 bgrewriteaof 往往会涉及大量磁盘操作
# 这样就会造成主进程在写aof文件的时候出现阻塞的情形
# 如果 no-appendfsync-on-rewrite 参数设置为no,是最安全的方式,不会丢失数据,但是要忍受阻塞的问题
# 如果设置为yes,这就相当于将 appendfsync 设置为no
# 这说明并没有执行磁盘操作,只是写入了缓冲区,因此这样并不会造成阻塞,因为没有竞争磁盘
# 但是如果这个时候 redis 挂掉,就会丢失数据
no-appendfsync-on-rewrite no
# aof rewrite过程中,是否采取增量文件同步策略
# rewrite过程中,每 32M 数据进行一次文件同步
# 这样可以减少aof大文件写入对磁盘的操作次数
aof-rewrite-incremental-fsync yes
# 是否加载破损的AOF文件
aof-load-truncated yes
# #################### 混合持久化 #####################
# 是否开启redis-4.x新增的混合持久化机制
aof-use-rdb-preamble no
# #################### Master #####################
# 必须绑定一个IP或者主机名,否则只识别127.0.0.1
# bind 192.168.239.101
bind node01
# 设置master的认证口令为redis
# requirepass redis
# backlog大小
repl-backlog-size 1mb
# 快照同步的超时时间
repl-timeout 60
# 开启无盘复制
repl-diskless-sync yes
# 无盘复制的延迟默认为5s,是为了等待更多的slave连接
repl-diskless-sync-delay 5
# 是否开启主从节点复制数据的延迟机制
# 当关闭时,主节点产生的命令数据无论大小都会及时地发送给从节点,这样主从之间延迟会变小
# 但增加了网络带宽的消耗。适用于主从之间的网络环境良好的场景
# 当开启时,主节点会合并较小的TCP数据包从而节省带宽。
# 默认发送时间间隔取决于Linux的内核,一般默认为40毫秒。
# 这种配置节省了带宽但增大主从之间的延迟。适用于主从网络环境复杂或带宽紧张的场景
repl-disable-tcp-nodelay no
# 触发快照同步的条件
# 如果增量同步的缓存大于256MB,或者超过60s大于64MB,则触发快照同步
client-output-buffer-limit slave 256mb 64mb 60
# 主从节点进行心跳的时间间隔
repl-ping-slave-period 10
(3) slave redis.conf 配置
修改两台 slave 节点的 redis_6379.conf,以下列出的修改过的或者相关的需要了解的配置,没有列出的保持默认即可:
#################### 基础配置 #####################
daemonize yes
port 6379
logfile /home/hadoop/logs/redis/6379/redis_6379.log
pidfile /home/hadoop/pid/redis/6379/redis_6379.pid
dir /home/hadoop/data/redis/6379
#################### RDB 相关 #####################
dbfilename dump.rdb
save 900 1
save 300 10
save 60 10000
rdbcompression yes
rdbchecksum yes
#################### AOF 相关 #####################
# 注意这里关闭slave节点的AOF机制
appendonly no
# #################### 混合持久化 #####################
# 是否开启redis-4.x新增的混合持久化机制
aof-use-rdb-preamble no
# #################### Slave #####################
# slave
# 必须绑定本台机器的IP或者主机名
bind node02
# 指定 master 节点的IP和port
slaveof node01 6379
# 开启从节点只读
slave-read-only yes
# 从节点在处于快照同步期间是否对外提供服务
slave-serve-stale-data yes
# 从节点的成为master的优先级,这个数字越高,优先级越高
slave-priority 100
# 如果 master 检测到 slave 的数量小于这个配置设置的值,将拒绝对外提供服务,0 代表,无论 slave 有几个都会对外提供服务
min-slaves-to-write 1
# 如果 master 发现大于等于 ${min-slaves-to-write} 个 slave 与自己的心跳超过此处配置的时间(单位s)
# 就拒绝对外提供服务
min-slaves-max-lag 10
# 节点间认证口令,需要与master的requirepass的值一致
# masterauth redis
另一个 slave 的配置中,只需要修改 bind
的值为自己的主机名或者IP即可,其他都和上面的配置一样。
(4) sentinel.conf 配置
修该3个节点的 sentinel_26379.conf,内容如下:
bind node01
port 26379
daemonize yes
dir /home/hadoop/data/redis/26379
# 文件需要提前创建好
logfile /home/hadoop/logs/redis/26379/sentinel_26379.log
# sentinel monitor [master-name] [master-ip] [master-port] [quorum]
# 这里的[master-name]可以自定义,但涉及到[master-name]的参数都要相同
sentinel monitor mymaster node01 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes
# sentinel auth-pass mymaster redis
# sentinel notification-script mymaster /tmp/xxx.sh
# sentinel client-reconfig-script mymaster /tmp/xxx.sh
不同的节点只需要修该bind
配置,修该为自己的IP或者主机名即可。
这些配置具体的解释以及配置的优化会在下面的内容中详细说明。
(5) 启动 Redis Sentinel 架构
- 首先启动 redis 主从架构
[hadoop@node01 ~]$ redis-server /home/hadoop/apps/redis-4.0.12/redis_6379.conf
# 其余两个节点执行相同的命令
- 确认3个redis 服务是否启动
[hadoop@node01 ~]$ redis-cli -h node01 -p 6379 ping
PONG
[hadoop@node01 ~]$ redis-cli -h node02 -p 6379 ping
PONG
[hadoop@node01 ~]$ redis-cli -h node03 -p 6379 ping
PONG
- 确认主从关系
[hadoop@node01 ~]$ redis-cli -h node01 -p 6379 info replication
# Replication
role:master
connected_slaves:2
min_slaves_good_slaves:2
slave0:ip=192.168.239.102,port=6379,state=online,offset=378,lag=0
slave1:ip=192.168.239.103,port=6379,state=online,offset=378,lag=0
......
[hadoop@node01 ~]$ redis-cli -h node02 -p 6379 info replication
# Replication
role:slave
master_host:node01
master_port:6379
...
slave_priority:100
slave_read_only:1
connected_slaves:0
......
- 启动 3个 sentinel 服务
edis-sentinel /home/hadoop/apps/redis-4.0.12/sentinel_26379.conf
或者
redis-server /home/hadoop/apps/redis-4.0.12/sentinel_26379.conf --sentinel
- 确认 sentinel 服务是否正常启动
[hadoop@node01 bin]$ redis-cli -h node01 -p 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=192.168.239.101:6379,slaves=2,sentinels=3
到这里,Redis Sentinel 架构搭建就已经成功搭建!
2. Redis Sentinel 配置详解
(1) quorum
# sentinel monitor [master-name] [master-ip] [master-port] [quorum]
sentinel monitor mymaster node01 6379 2
我们的配置中,quorum = 2,quorum 参数用于故障发现和判定,例如将 quorum 配置为2,代表至少有2个Sentinel节点认为主节点不可达,那么这个不可达的判定才是客观的。quorum 设置的越小,那么达到客观下线的条件越宽松,反之越严格。一般建议将其设置为Sentinel节点的一半加1。
同时 quorum 还与 Sentinel 节点的领导者选举有关,至少要有max(quorum,num(sentinels) / 2 + 1)
个Sentinel节点参与选举,才能选出领导者Sentinel,从而完成故障转移。例如有5个Sentinel节点,quorum=4,那么至少要有4个在线Sentinel节点才可以进行领导者选举。
(2) down-after-milliseconds
sentinel down-after-milliseconds mymaster 30000
每个Sentinel节点都要通过定期发送ping命令来判断Redis数据节点和其余Sentinel节点是否可达,如果超过了down-after-milliseconds
配置的时间(单位ms)且没有有效的回复,则判定节点不可达,这个配置是对节点失败判定的重要依据。
优化说明:down-after-milliseconds越大,代表Sentinel节点对于节点不可达的条件越宽松,反之越严格。
条件宽松有可能带来的问题是节点确实不可达了,那么应用方需要等待故障转移的时间越长,也就意味着应用方故障时间可能越长。
条件严格虽然可以及时发现故障完成故障转移,但是也存在一
定的误判率。
配置down-after-milliseconds
虽然指定master-name,但实际上对Sentinel节点、主节点、从节点的失败判定的超时时间都是这个值。
(3) parallel-syncs
sentinel parallel-syncs mymaster 1
当Sentinel节点集合对主节点故障判定达成一致时,Sentinel领导者节点会做故障转移操作,选出新的主节点,原来的从节点会向新的主节点发起复制操作,parallel-syncs就是用来限制在一次故障转移之后,每次向新的主节点发起复制操作的从节点个数。如果这个参数配置的比较大,那么多个从节点会向新的主节点同时发起复制操作,尽管复制操作通常不会阻塞主节点,但是同时向主节点发起复制,必然会对主节点所在的机器造成一定的网络和磁盘IO开销。如果设置的这个值比较大,由于每个slave从新的master同步数据成功后才认为故障转移成功,这里限制同时向新的master同步数据的slave个数,必然会导致故障转移的时间边长。
(4) sentinel failover-timeout
sentinel failover-timeout mymaster 180000
failover-timeout通常被解释成故障转移超时时间,但实际上它作用于故障转移的各个阶段:
A. 选出合适从节点。
B. 晋升选出的从节点为主节点。
C. 命令其余从节点复制新的主节点。
D. 等待原主节点恢复后命令它去复制新的主节点。
failover-timeout的作用具体体现在四个方面:
- 如果Redis Sentinel对一个主节点故障转移失败,那么下次再对该主节点做故障转移的起始时间是failover-timeout的2倍。
- 在B阶段时,如果Sentinel节点向A阶段选出来的从节点执行
slaveof no one
一直失败(例如该从节点此时出现故障),当此过程超过failover-timeout时,则故障转移失败。 - 在B阶段如果执行成功,Sentinel节点还会执行info命令来确认A阶段选出来的节点确实晋升为主节点,如果此过程执行时间超过failovertimeout时,则故障转移失败。
- 如果C阶段执行时间超过了failover-timeout(不包含复制时间),则故障转移失败。注意即使超过了这个时间,Sentinel节点也会最终配置从节点去同步最新的主节点。
(5) auth-pass
# sentinel auth-pass mymaster redis
如果Sentinel监控的主节点配置了密码(redis.conf中的requirepass),sentinel auth-pass 配置通过添加主节点的密码,防止Sentinel节点对主节点无法监控。
(6) notification-script
# sentinel notification-script mymaster /tmp/xxx.sh
sentinel notification-script的作用是在故障转移期间,当一些警告级别的Sentinel事件发生(指重要事件,例如-sdown:客观下线、-odown:主观下线)时,会触发对应路径的脚本,并向脚本发送相应的事件参数。这些脚本利用这些参数作为邮件或者短信报警依据。
(7) client-reconfig-script
# sentinel client-reconfig-script mymaster /tmp/xxx.sh
sentinel client-reconfig-script的作用是在故障转移结束后,会触发对应路径的脚本,并向脚本发送故障转移结果的相关参数。和notification-script类似,设置的脚本会接收每个Sentinel节点传过来的故障转移结果参数,并触发类似短信和邮件报警。
当故障转移结束,每个Sentinel节点可以将故障转移的结果发送给对应的脚本,具体参数如下:
:主节点名。 :Sentinel节点的角色,分别是leader和observer,leader代表当前Sentinel节点是领导者,是它进行的故障转移;observer是其余Sentinel节点。 :原主节点的ip地址。 :原主节点的端口。 :新主节点的ip地址。 :新主节点的端口。
有关sentinel notification-script和sentinel client-reconfig-script有几点需要注意:
必须有可执行权限。 开头必须包含shell脚本头(例如#!/bin/sh),否则事件发生时Redis将无法执行脚本。 - Redis规定脚本的最大执行时间不能超过60秒,超过后脚本将被杀掉。
- 如果shell脚本以exit 1结束,那么脚本稍后重试执行。如果以exit 2或者更高的值结束,那么脚本不会重试。正常返回值是exit 0。
- 如果需要运维的Redis Sentinel比较多,建议不要使用这种脚本的形式来进行通知,这样会增加部署的成本。
3. Redis Sentinel 启动日志分析
(1) sentinel.conf 的变化
启动之前,sentinel_26379.conf中的内容如下:
bind node01
port 26379
daemonize yes
dir /home/hadoop/data/redis/26379
logfile /home/hadoop/logs/redis/26379/sentinel_26379.log
sentinel monitor mymaster node01 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes
启动之后,文件内容变为:
bind node01
port 26379
daemonize yes
dir "/home/hadoop/data/redis/26379"
logfile "/home/hadoop/logs/redis/26379/sentinel_26379.log"
sentinel deny-scripts-reconfig yes
sentinel monitor mymaster 192.168.239.101 6379 2
sentinel config-epoch mymaster 0
sentinel current-epoch 0
sentinel myid 8a692e7438e7086c98e3fafbb72337e21ada032d
sentinel leader-epoch mymaster 0
sentinel known-slave mymaster 192.168.239.103 6379
sentinel known-slave mymaster 192.168.239.102 6379
sentinel known-sentinel mymaster 192.168.239.103 26379 94b8a0165d93e9ad8288f0a77a855b59a6c5fab4
sentinel known-sentinel mymaster 192.168.239.102 26379 42b932cf4f1a5bc53f5cde7275f9ae0da1026057
变化是:
- 去掉了一些默认配置,例如parallel-syncs、failover-timeout。
- 添加了配置版本相关参数。
(2) 故障转移日志分析
- 查看 master 信息
[hadoop@node01 redis-4.0.12]$ redis-cli -h node01 -p 26379
node01:26379> sentinel master mymaster
1) "name"
2) "mymaster"
3) "ip"
4) "192.168.239.101"
5) "port"
6) "6379"
7) "runid"
8) "ecce013361abe093768ef647cfee7ad5f058e73b"
......
- 杀死 master 节点的 redis 服务
[hadoop@node01 redis-4.0.12]$ ps -ef | grep redis
hadoop 7139 1 0 08:58 ? 00:00:08 redis-server node01:6379
hadoop 7363 1 0 09:10 ? 00:00:08 redis-sentinel node01:26379 [sentinel]
hadoop 7431 7042 0 10:15 pts/0 00:00:00 grep --color=auto redis
[hadoop@node01 redis-4.0.12]$ kill -9 7139
- 查看 master 日志
# 这些日志都是启动 master 后打印的
# kill 掉 master 进程后没有打印任何日志
7139:M 28 Feb 08:58:31.656 * Starting BGSAVE for SYNC with target: disk
7139:M 28 Feb 08:58:31.656 * Background saving started by pid 7146
7146:C 28 Feb 08:58:31.658 * DB saved on disk
7146:C 28 Feb 08:58:31.658 * RDB: 4 MB of memory used by copy-on-write
7139:M 28 Feb 08:58:31.690 * Background saving terminated with success
7139:M 28 Feb 08:58:31.690 * Synchronization with slave 192.168.239.103:6379 succeeded
# 由于是使用 kill 的方式杀死 master 进程
# 所以 master 直接断开,没有做任何的数据持久化
- 查看node02节点(slave)的日志
# 与 master 断开连接
6845:S 28 Feb 10:15:15.702 # Connection with master lost.
# 缓存失联的 master 状态信息
6845:S 28 Feb 10:15:15.702 * Caching the disconnected master state.
6845:S 28 Feb 10:15:16.239 * Connecting to MASTER 192.168.239.101:6379
6845:S 28 Feb 10:15:16.240 * MASTER <-> SLAVE sync started
# 请求与 master 同步数据失败
6845:S 28 Feb 10:15:16.240 # Error condition on socket for SYNC: Connection refused
# node02 节点将升级为 master
......
# 清除旧的 master 的状态信息
6845:M 28 Feb 10:15:46.131 * Discarding previously cached master state.
# node02 提升为 master
6845:M 28 Feb 10:15:46.131 * MASTER MODE enabled (user request from 'id=15 addr=192.168.239.103:34822 fd=12 name=sentinel-94b8a016-cmd age=3949 idle=0 flags=x db=0 sub=0 psub=0 multi=3 qbuf=0 qbuf-free=32768 obl=36 oll=0 omem=0 events=r cmd=exec')
# 重写配置
6845:M 28 Feb 10:15:46.132 # CONFIG REWRITE executed with success.
# node03节点请求从node02节点复制数据
Slave 192.168.239.103:6379 asks for synchronization
# node02 节点同意了数据同步的请求,这两个节点成功同步数据
6845:M 28 Feb 10:15:47.134 * Partial resynchronization request from 192.168.239.103:6379 accepted. Sending 458 bytes of backlog starting from offset 970803.
- 查看node03节点(slave)的日志
# 与 master node01 失联
6607:S 28 Feb 10:15:15.708 # Connection with master lost.
6607:S 28 Feb 10:15:15.708 * Caching the disconnected master state.
6607:S 28 Feb 10:15:15.953 * Connecting to MASTER 192.168.239.101:6379
6607:S 28 Feb 10:15:15.953 * MASTER <-> SLAVE sync started
6607:S 28 Feb 10:15:15.954 # Error condition on socket for SYNC: Connection refused
......
# 新的 master:node02:6379 准备就绪
6607:S 28 Feb 10:15:46.910 * SLAVE OF 192.168.239.102:6379 enabled (user request from 'id=15 addr=192.168.239.103:33915 fd=12 name=sentinel-94b8a016-cmd age=3949 idle=0 flags=x db=0 sub=0 psub=0 multi=3 qbuf=145 qbuf-free=32623 obl=36 oll=0 omem=0 events=r cmd=exec')
# 重写配置
6607:S 28 Feb 10:15:46.910 # CONFIG REWRITE executed with success.
# 连接到新的 master
6607:S 28 Feb 10:15:47.139 * Connecting to MASTER 192.168.239.102:6379
# 开始从新的 master 同步数据
6607:S 28 Feb 10:15:47.139 * MASTER <-> SLAVE sync started
6607:S 28 Feb 10:15:47.139 * Non blocking connect for SYNC fired the event.
# 新master 回复了 slave 的ping命令
6607:S 28 Feb 10:15:47.139 * Master replied to PING, replication can continue...
6607:S 28 Feb 10:15:47.140 * Trying a partial resynchronization (request 48288f005d4b8d4420c2d5081cb640081600e525:970803).
# 成功发送同步数据请求
6607:S 28 Feb 10:15:47.140 * Successful partial resynchronization with master.
6607:S 28 Feb 10:15:47.140 # Master replication ID changed to 907b3e69f9e1ae789481c524f285834ea4d55445
# master 接受了 同步数据请求
6607:S 28 Feb 10:15:47.140 * MASTER <-> SLAVE sync: Master accepted a Partial Resynchronization.
- 在sentinel.conf中查看每个节点的 sentinel ID
# node01
sentinel myid 8a692e7438e7086c98e3fafbb72337e21ada032d
# node02
sentinel myid 42b932cf4f1a5bc53f5cde7275f9ae0da1026057
# node03
sentinel myid 94b8a0165d93e9ad8288f0a77a855b59a6c5fab4
- 查看 sentinel-0 日志
# 确认 node01 主观下线
7363:X 28 Feb 10:15:45.795 # +sdown master mymaster 192.168.239.101 6379
# 更新配置版本为2
7363:X 28 Feb 10:15:45.892 # +new-epoch 2
# # node03 请求成为leader,开始投票
7363:X 28 Feb 10:15:45.893 # +vote-for-leader 94b8a0165d93e9ad8288f0a77a855b59a6c5fab4 2
# node03 成为leader,从leader更新配置
7363:X 28 Feb 10:15:46.905 # +config-update-from sentinel 94b8a0165d93e9ad8288f0a77a855b59a6c5fab4 192.168.239.103 26379 @ mymaster 192.168.239.101 6379
# 从 leader 那里得到的新的主从架构信息如下:
# master 从 node01 切换为 node02
7363:X 28 Feb 10:15:46.905 # +switch-master mymaster 192.168.239.101 6379 192.168.239.102 6379
# node03 成为 node02 的 slave
7363:X 28 Feb 10:15:46.905 * +slave slave 192.168.239.103:6379 192.168.239.103 6379 @ mymaster 192.168.239.102 6379
# node01 成为 node02 的 slave
7363:X 28 Feb 10:15:46.905 * +slave slave 192.168.239.101:6379 192.168.239.101 6379 @ mymaster 192.168.239.102 6379
# node01 这个 slave 主观下线(因为 node01 还没启动)
7363:X 28 Feb 10:16:16.942 # +sdown slave 192.168.239.101:6379 192.168.239.101 6379 @ mymaster 192.168.239.102 6379
- 查看 sentinel-1 日志
# 确认 master 主观下线
6961:X 28 Feb 10:15:45.851 # +sdown master mymaster 192.168.239.101 6379
# 更新配置版本为2
6961:X 28 Feb 10:15:45.891 # +new-epoch 2
# node03请求成为leader,开始投票
6961:X 28 Feb 10:15:45.892 # +vote-for-leader 94b8a0165d93e9ad8288f0a77a855b59a6c5fab4 2
# 确认 master 客观下线
6961:X 28 Feb 10:15:45.909 # +odown master mymaster 192.168.239.101 6379 #quorum 3/2
6961:X 28 Feb 10:15:45.909 # Next failover delay: I will not start a failover before Thu Feb 28 10:21:46 2019
# 从 node03(leader) 更新配置
6961:X 28 Feb 10:15:46.904 # +config-update-from sentinel 94b8a0165d93e9ad8288f0a77a855b59a6c5fab4 192.168.239.103 26379 @ mymaster 192.168.239.101 6379
# 得到的新的主从架构关系如下:
# master 从 node01 切换为 node02
6961:X 28 Feb 10:15:46.904 # +switch-master mymaster 192.168.239.101 6379 192.168.239.102 6379
# node03 成为 node02 的 slave
6961:X 28 Feb 10:15:46.904 * +slave slave 192.168.239.103:6379 192.168.239.103 6379 @ mymaster 192.168.239.102 6379
# node01 成为 node02 的 slave
6961:X 28 Feb 10:15:46.904 * +slave slave 192.168.239.101:6379 192.168.239.101 6379 @ mymaster 192.168.239.102 6379
# node01 这个 slave 主观下线(因为 node01 还没启动
6961:X 28 Feb 10:16:16.928 # +sdown slave 192.168.239.101:6379 192.168.239.101 6379 @ mymaster 192.168.239.102 6379
- 查看 sentinel-2 日志
# 确认 node01 主观下线
6846:X 28 Feb 10:15:45.842 # +sdown master mymaster 192.168.239.101 6379
# 确认 node01 客观下线
# 这里也可以看出,谁先确认 master 客观下线,谁就会先申请成为故障转移的 leader
# 而先申请的就会成为 leader
6846:X 28 Feb 10:15:45.895 # +odown master mymaster 192.168.239.101 6379 #quorum 2/2
# 更新配置版本
6846:X 28 Feb 10:15:45.895 # +new-epoch 2
# 尝试进行故障转移
6846:X 28 Feb 10:15:45.895 # +try-failover master mymaster 192.168.239.101 6379
# 开启为 node03 投票
6846:X 28 Feb 10:15:45.896 # +vote-for-leader 94b8a0165d93e9ad8288f0a77a855b59a6c5fab4 2
# 得到 node01 投的一票
6846:X 28 Feb 10:15:45.898 # 8a692e7438e7086c98e3fafbb72337e21ada032d voted for 94b8a0165d93e9ad8288f0a77a855b59a6c5fab4 2
# 得到 node02 投的一票
6846:X 28 Feb 10:15:45.899 # 42b932cf4f1a5bc53f5cde7275f9ae0da1026057 voted for 94b8a0165d93e9ad8288f0a77a855b59a6c5fab4 2
# 当选为执行故障转移的 leader
6846:X 28 Feb 10:15:45.997 # +elected-leader master mymaster 192.168.239.101 6379
6846:X 28 Feb 10:15:45.997 # +failover-state-select-slave master mymaster 192.168.239.101 6379
# 选择 node02 成为新的 master
6846:X 28 Feb 10:15:46.074 # +selected-slave slave 192.168.239.102:6379 192.168.239.102 6379 @ mymaster 192.168.239.101 6379
# 让 node02 执行 slaveof-noone 命令
6846:X 28 Feb 10:15:46.074 * +failover-state-send-slaveof-noone slave 192.168.239.102:6379 192.168.239.102 6379 @ mymaster 192.168.239.101 6379
# 等待 node02 成为 master
6846:X 28 Feb 10:15:46.137 * +failover-state-wait-promotion slave 192.168.239.102:6379 192.168.239.102 6379 @ mymaster 192.168.239.101 6379
# 确认 node02 成为 master
6846:X 28 Feb 10:15:46.858 # +promoted-slave slave 192.168.239.102:6379 192.168.239.102 6379 @ mymaster 192.168.239.101 6379
# 重新配置 slave
6846:X 28 Feb 10:15:46.858 # +failover-state-reconf-slaves master mymaster 192.168.239.101 6379
# 让 node03 去复制 node02
6846:X 28 Feb 10:15:46.909 * +slave-reconf-sent slave 192.168.239.103:6379 192.168.239.103 6379 @ mymaster 192.168.239.101 6379
# node03 复制 node02 过程进行中
6846:X 28 Feb 10:15:47.874 * +slave-reconf-inprog slave 192.168.239.103:6379 192.168.239.103 6379 @ mymaster 192.168.239.101 6379
# node03 复制 node02 完成
6846:X 28 Feb 10:15:47.874 * +slave-reconf-done slave 192.168.239.103:6379 192.168.239.103 6379 @ mymaster 192.168.239.101 6379
# 故障转移结束
6846:X 28 Feb 10:15:47.965 # +failover-end master mymaster 192.168.239.101 6379
# 发布消息,包括切换了 master,主从架构的变化等信息
6846:X 28 Feb 10:15:47.965 # +switch-master mymaster 192.168.239.101 6379 192.168.239.102 6379
6846:X 28 Feb 10:15:47.965 * +slave slave 192.168.239.103:6379 192.168.239.103 6379 @ mymaster 192.168.239.102 6379
6846:X 28 Feb 10:15:47.965 * +slave slave 192.168.239.101:6379 192.168.239.101 6379 @ mymaster 192.168.239.102 6379
6846:X 28 Feb 10:16:18.048 # +sdown slave 192.168.239.101:6379 192.168.239.101 6379 @ mymaster 192.168.239.102 6379
- 启动node01节点的redis服务
[hadoop@node01 redis-4.0.12]$ redis-server ./redis_6379.conf
- node01的redis服务日志
# 连接到新的master node02
7471:S 28 Feb 11:46:12.693 * Connecting to MASTER 192.168.239.102:6379
# 开始从 node02 复制数据
7471:S 28 Feb 11:46:12.693 * MASTER <-> SLAVE sync started
......
# 复制成功
7471:S 28 Feb 11:47:03.170 * Background saving terminated with success
- node02的redis服务日志
# node01 请求同步数据
6845:M 28 Feb 10:15:47.134 * Slave 192.168.239.103:6379 asks for synchronization
6845:M 28 Feb 10:15:47.134 * Partial resynchronization request from 192.168.239.103:6379 accepted. Sending 458 bytes of backlog starting from offset 970803.
6845:M 28 Feb 11:46:12.693 * Slave 192.168.239.101:6379 asks for synchronization
6845:M 28 Feb 11:46:12.693 * Partial resynchronization not accepted: Replication ID mismatch (Slave asked for '3c646f5c318f604379978850ffefd54372e5218c', my replication IDs are '907b3e69f9e1ae789481c524f285834ea4d55445' and '48288f005d4b8d4420c2d5081cb640081600e525')
# 开始同步数据
6845:M 28 Feb 11:46:12.693 * Starting BGSAVE for SYNC with target: disk
6845:M 28 Feb 11:46:12.694 * Background saving started by pid 7055
7055:C 28 Feb 11:46:12.804 * DB saved on disk
7055:C 28 Feb 11:46:12.804 * RDB: 6 MB of memory used by copy-on-write
6845:M 28 Feb 11:46:12.904 * Background saving terminated with success
# 同步数据成功
6845:M 28 Feb 11:46:12.904 * Synchronization with slave 192.168.239.101:6379 succeeded
- node03的redis服务日志
# node03 没有产生新日志
- sentinel 日志(3台节点新增的日志都一样)
# 不再认为 node01 主观下线
6846:X 28 Feb 11:46:02.752 # -sdown slave 192.168.239.101:6379 192.168.239.101 6379 @ mymaster 192.168.239.102 6379
4. 其他 Redis Sentinel 的知识点
(1) 监控多个 master
Redis Sentinel可以同时监控多个主节点,具体拓扑图类似于下图:
配置方法也比较简单,只需要指定多个master-name来区分不同的主节点即可,例如下面的配置监控master-1(node01:6379)和master-2(node04:6379)两个主节点:
sentinel monitor master-1 node01 6379 2
sentinel down-after-milliseconds master-1 60000
sentinel failover-timeout master-1 180000
sentinel parallel-syncs master-1 1
sentinel monitor master-2 node04 6379 2
sentinel down-after-milliseconds master-2 10000
sentinel failover-timeout master-2 180000
sentinel parallel-syncs master-2 1
(2) 动态设置参数
Sentinel节点支持动态地设置参数,但并不是支持所有的参数,具体使用方法如下:
sentinel set
参数 | 使用方法 |
---|---|
quorum | sentinel set mymaster quorum 2 |
down-after-milliseconds | sentinel set mymaster down-after-milliseconds 30000 |
parallel-syncs | sentinel set mymaster parallel-syncs 1 |
failover-timeout | sentinel set mymaster failover-timeout 180000 |
auth-pass | sentinel set mymaster auth-pass xxx |
notification-script | sentinel set mymaster notification-script /path/xxx.sh |
client-reconfig-script | sentinel set mymaster client-reconfig-script /path/xxx.sh |
注意点:
- sentinel set命令只对当前Sentinel节点有效。
- sentinel set命令如果执行成功会立即刷新配置文件,这点和Redis普通数据节点设置配置需要执行config rewrite刷新到配置文件不同。
- 建议所有Sentinel节点的配置尽可能一致,这样在故障发现和转移时比较容易达成一致。
- Sentinel对外不支持config命令。
(3) Redis Sentinel 部署建议
Sentinel节点不应该部署在一台物理机器上。这里特意强调物理机是因为一台物理机做成了若干虚拟机或者现今比较流行的容器,它们虽然有不同的IP地址,但实际上它们都是同一台物理机,同一台物理机意味着如果这台机器有什么硬件故障,所有的虚拟机都会受到影响,为了实现Sentinel节点集合真正的高可用,请勿将Sentinel节点部署在同一台物理机器上。
部署至少三个且奇数个的Sentinel节点。3个以上是通过增加Sentinel节点的个数提高对于故障判定的准确性,因为领导者选举需要至少一半加1个节点,奇数个节点在相同容错性的基础上可以节省一个节点。这里怎么理解可以节省1个节点?
3个节点,要求 3/2 + 1 = 1 + 1 = 2 个sentinel节点同时在线才可以选举 leader,也就是说最多允许1个sentinel挂掉。
4个节点,要求 4/2 + 1 = 2 + 1 = 3个sentinel节点同时在线才可以选举 leader,也就是说最多允许1个sentinel挂掉。
也就是说,3个节点和4个节点都是最多允许1个节点挂掉,那么他们的容错性相同,但是3个节点就是可以节省1个节点来达到相同的容错性。多套redis主从架构使用一套 sentinel 集群进行监控还是多套 sentinel 集群进行监控?
方案一:一套Sentinel,很明显这种方案在一定程度上降低了维护成本,因为只需要维护固定个数的Sentinel节点,集中对多个Redis数据节点进行管理就可以了。但是这同时也是它的缺点,如果这套Sentinel节点集合出现异常,可能会对多个Redis数据节点造成影响。还有如果监控的Redis数据节点较多,会造成Sentinel节点产生过多的网络连接,也会有一定的影响。
方案二:多套Sentinel,显然这种方案的优点和缺点和上面是相反的,每个Redis主节点都有自己的Sentinel节点集合,会造成资源浪费。但是优点也很明显,每套Redis Sentinel都是彼此隔离的。
建议:
如果Sentinel节点集合监控的是同一个业务的多个主节点集合,那么使用方案一,否则一般建议采用方案二。
(4) Redis Sentinel 运维
<1> 更换主节点
执行以下命令:
sentinel failover
# 例如
sentinel failover mymaster
如果想切换到指定的某台从节点上,那么需要先把其他的从节点的 priority 设置为0(设置为0,代表禁止该节点成为主节点),当切换成功后,再把其他从节点的 priority 复原即可。
<2> 增加 slave
在新加的 slave 的 redis.conf 文件中添加slaveof [master-ip] [master-port]
的配置,使用redis-server
启动即可,它将被Sentinel节点自动发现。
<3> slave 下线
- 临时下线
临时下线只需要关闭某个从节点的redis服务即可。临时下线后,sentinel节点还是会监控这个已下线的从节点。 - 永久下线
永久下线首先关闭从节点的服务,然后让sentinel集群不再监控该节点。因为定期监控也会造成一定的网络资源浪费,sentinel更新监控节点的命令为:
sentinel reset master-name
<4> 增加 sentinel 节点
在新加的 sentinel 节点的 sentinel.conf 文件中设置sentinel monitor
和其他配置,使用redis-sentinel启动即可,它将被其余sentinel节点自动发现。
<5> sentinel 节点下线
与 slave 下线一样,如果是临时下线,关闭服务即可。如果是永久下线,关闭服务后执行sentinel reset [master-name]
命令。