Redis哨兵配置及原理笔记

第一部分 原理

一、Sentinel的作用
1、Master状态监测

2、如果Master 异常,则会进行Master-slave 转换,将其中一个Slave作为Master,将之前的Master恢复正常后作为Slave

3、Master-Slave切换后,master_redis.conf、slave_redis.conf和sentinel.conf的内容都会发生改变,即master_redis.conf中会多一行slaveof的配置,sentinel.conf的监控目标会随之调换


二、Sentinel的工作方式
1、每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他 Sentinel 实例发送一个 PING 命令

2、如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel 标记为主观下线。

3、如果一个Master被标记为主观下线,则正在监视这个Master的所有 Sentinel 要以每秒一次的频率确认Master的确进入了主观下线状态。

4、当有足够数量的 Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态, 则Master会被标记为客观下线

5、在一般情况下, 每个 Sentinel 会以每 10 秒一次的频率向它已知的所有Master,Slave发送 INFO 命令

6、当Master被 Sentinel 标记为客观下线时,Sentinel 向下线的 Master 的所有 Slave 发送 INFO 命令的频率会从 10 秒一次改为每秒一次

7、若没有足够数量的 Sentinel 同意 Master 已经下线, Master 的客观下线状态就会被移除。
若 Master 重新向 Sentinel 的 PING 命令返回有效回复, Master 的主观下线状态就会被移除。

第二部分 配置

Redis哨兵是在主从复制的基础上增加哨兵机制。

主从配置可参考文章:《Redis主从复制配置笔记

这里重点阐述哨兵配置

声明:哨兵功能全部配置文件都可以不设置密码,如果设置了就保持一直的密码。这里为了说明方便,没有设置密码,也没有说明密码相关的配置。建议初学者学习实践不要设置密码配置。【为什么要声明这个呢,观察故障迁移的时候,发现没有错误却无法迁移,很多资料都是设置了密码的,甚至怀疑是没有设置密码的缘故,故而特此声明,希望大家不要踩坑

假设主从配置为一主二从
主:10.235.25.241:6379
从:10.235.25.241:6380
从:10.235.25.241:6381
在主上查看到如下信息:

10.235.25.241:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=43,lag=0
slave1:ip=127.0.0.1,port=6381,state=online,offset=43,lag=0
master_repl_offset:43
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:42

一、基础版,只配置一个哨兵

redis源码包中有配置文件模板sentinel.conf
0、配置哨兵监听主库

cp /usr/local/redis/redis-4.0.2/sentinel.conf /etc/sentinel.conf

vim /etc/sentinel.conf

daemonize yes
logfile /var/log/sentinel.log
sentinel monitor mymaster 127.0.0.1 6379 1

注意:sentinel monitor最后一个选项的数字,表明判断主服务器失效至少需要几个哨兵同意。

1、启动哨兵

/usr/bin/redis-sentinel /etc/sentinel.conf

# 查看进程,哨兵端口号默认为26379
ps -ef | grep redis | grep -v grep
root     31119     1  0 17:33 ?        00:00:00 /usr/bin/redis-server 0.0.0.0:6379
root     31129     1  0 17:33 ?        00:00:00 /usr/bin/redis-server 0.0.0.0:6380
root     31142     1  0 17:33 ?        00:00:00 /usr/bin/redis-server 0.0.0.0:6381
root     31438     1  0 17:46 ?        00:00:00 /usr/bin/redis-sentinel *:26379 [sentinel]

2、查看哨兵
2.1 通过日志

tail -f /var/log/sentinel.log

11286:X 07 Dec 02:32:43.934 # Sentinel ID is 2a4bfbd22a38169473b9fe3068ba1267b6baaa32
11286:X 07 Dec 02:32:43.934 # +monitor master mymaster 127.0.0.1 6379 quorum 1
11286:X 07 Dec 02:32:43.935 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
11286:X 07 Dec 02:32:44.001 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379

观察日志分别出现+master, +slave, +slave表明正常。如果不正常,可以查看后文的异常说明。

2.2 通过sentinel

/usr/bin/redis-cli -p 26379 -h 10.235.25.241 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=1

如果观察哨兵正常,可以继续往下走
3、故障迁移
3.1 kill 主库redis

ps -ef | grep redis
root       743     1  0 18:34 ?        00:00:00 /usr/bin/redis-server 0.0.0.0:6379
root       782     1  0 18:35 ?        00:00:00 /usr/bin/redis-server 0.0.0.0:6380
root       794     1  0 18:35 ?        00:00:00 /usr/bin/redis-server 0.0.0.0:6381
root       806     1  0 18:35 ?        00:00:00 /usr/bin/redis-sentinel *:26379 [sentinel]
root      1047   351  0 18:45 pts/0    00:00:00 grep --color=auto redis
kill 743

3.2、观察迁移过程

tail -f /var/log/sentinel.log

11286:X 07 Dec 02:33:34.992 # +sdown master mymaster 127.0.0.1 6379
11286:X 07 Dec 02:33:34.992 # +odown master mymaster 127.0.0.1 6379 #quorum 1/1
11286:X 07 Dec 02:33:34.993 # +new-epoch 2
11286:X 07 Dec 02:33:34.993 # +try-failover master mymaster 127.0.0.1 6379
11286:X 07 Dec 02:33:35.047 # +vote-for-leader 2a4bfbd22a38169473b9fe3068ba1267b6baaa32 2
11286:X 07 Dec 02:33:35.048 # +elected-leader master mymaster 127.0.0.1 6379
11286:X 07 Dec 02:33:35.048 # +failover-state-select-slave master mymaster 127.0.0.1 6379
11286:X 07 Dec 02:33:35.100 # +selected-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
11286:X 07 Dec 02:33:35.100 * +failover-state-send-slaveof-noone slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
11286:X 07 Dec 02:33:35.176 * +failover-state-wait-promotion slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
11286:X 07 Dec 02:33:35.973 # +promoted-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
11286:X 07 Dec 02:33:35.973 # +failover-state-reconf-slaves master mymaster 127.0.0.1 6379
11286:X 07 Dec 02:33:35.986 * +slave-reconf-sent slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
11286:X 07 Dec 02:33:36.978 * +slave-reconf-inprog slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
11286:X 07 Dec 02:33:36.979 * +slave-reconf-done slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
11286:X 07 Dec 02:33:37.049 # +failover-end master mymaster 127.0.0.1 6379
11286:X 07 Dec 02:33:37.049 # +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6380
11286:X 07 Dec 02:33:37.049 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
11286:X 07 Dec 02:33:37.049 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
11286:X 07 Dec 02:34:07.105 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380

重点是看到下面这一行,把主库迁移到6380上

11286:X 07 Dec 02:33:37.049 # +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6380

3.3、验证迁移后的主库
新开一个窗口,连接6380

/usr/bin/redis-cli -h 10.235.25.241 -p 6380
10.235.25.241:6380> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6381,state=online,offset=25987,lag=0
master_repl_offset:26120
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:26119

通过info replication可以看到role变为master,并且只有一个slave 6381

同时测试已经有write权限

10.235.25.241:6380> set niliu 200
OK
10.235.25.241:6380> get niliu
"200"

3.4、恢复原master 6379

/usr/bin/redis-server /etc/redis.conf

观察哨兵的行为

tail -f /var/log/sentinel.log

11286:X 07 Dec 02:44:40.585 # -sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
11286:X 07 Dec 02:44:50.523 * +convert-to-slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380

可以看到原master 6379 恢复后,成为slave,可以在新master 6380中查看

/usr/bin/redis-cli -h 10.235.25.241 -p 6380
10.235.25.241:6380> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6381,state=online,offset=52804,lag=0
slave1:ip=127.0.0.1,port=6379,state=online,offset=52804,lag=0
master_repl_offset:52804
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:52803

4、从库故障
4.1 kill 从库redis 6381

ps -ef | grep redis
root     11166     1  0 02:31 ?        00:00:00 /usr/bin/redis-server 0.0.0.0:6380
root     11177     1  0 02:31 ?        00:00:00 /usr/bin/redis-server 0.0.0.0:6381
root     11286     1  0 02:32 ?        00:00:01 /usr/bin/redis-sentinel *:26379 [sentinel]
root     11602     1  0 02:44 ?        00:00:00 /usr/bin/redis-server 0.0.0.0:6379

kill 

4.2、观察哨兵的行为
需要等30s才有结果,提示slave 6381主管下线。

tail -f /var/log/sentinel.log

11286:X 07 Dec 02:51:21.808 # +sdown slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380

5、异常分析
5.1、启动了哨兵,发现sentinel.log只有master日志,没有slave日志。
检查/etc/sentinel.conf最后是否有以下内容,如果有删除重启再试。
之前如果启动过sentinel, 配置文件会写入内容,影响下次启动。

# Generated by CONFIG REWRITE
sentinel known-slave mymaster 127.0.0.1 6379
sentinel known-slave mymaster 127.0.0.1 6381
sentinel current-epoch 2

5.2、查看哨兵信息提示DENIED Redis is running in protected mode because protected mode is enabled。
打开/etc/sentinel.conf。找到protected-mode no这行,把注释打开。默认是yes,受保护模式。

redis3.2版本后新增protected-mode配置,默认是yes,即开启。设置外部网络连接redis服务,设置方式如下:
a、关闭protected-mode模式,此时外部网络可以直接访问
b、开启protected-mode保护模式,需配置bind ip或者设置访问密码

/usr/bin/redis-cli -p 26379 -h 10.235.25.241
10.235.25.241:26379> info
DENIED Redis is running in protected mode because protected mode is enabled, no bind address was specified, no authentication password is requested to clients. In this mode connections are only accepted from the loopback interface. If you want to connect from external computers to Redis you may adopt one of the following solutions: 1) Just disable protected mode sending the command 'CONFIG SET protected-mode no' from the loopback interface by connecting to Redis from the same host the server is running, however MAKE SURE Redis is not publicly accessible from internet if you do so. Use CONFIG REWRITE to make this change permanent. 2) Alternatively you can just disable the protected mode by editing the Redis configuration file, and setting the protected mode option to 'no', and then restarting the server. 3) If you started the server manually just for testing, restart it with the '--protected-mode no' option. 4) Setup a bind address or an authentication password. NOTE: You only need to do one of the above things in order for the server to start accepting connections from the outside.

注:也可通过命令查看/usr/bin/redis-cli -p 26379 -h 10.235.25.241 info sentinel

5.3、master挂了,故障不迁移,log中仅有master sdown,没有其他提示。
检查/etc/sentinel.conf中配置的sentinel monitor最后一个选项的数字,表明判断主服务器失效至少需要几个哨兵同意。我一开始盲目参考网络配置的是2,导致一直迁移不了。

5.4、如果设置了密码,故障不迁移可参考文章《redis sentinel不能监测到slave master宕机后不能主从切换

6、小工具
过程中需要频繁重启服务,可以下列命令,全部kill, 全部重启。

# kill全部redis进程
ps -ef | grep redis | grep -v grep | awk '{print $2}' | xargs -i kill {}
# 重启
/usr/bin/redis-server /etc/redis.conf
/usr/bin/redis-server /etc/redis_6380.conf
/usr/bin/redis-server /etc/redis_6381.conf
/usr/bin/redis-sentinel /etc/sentinel.conf

二、进阶版,配置多个哨兵
待整理

参考:
Redis中文文档:Redis 的 Sentinel 文档
Redis Sentinel Documentation
深入浅出Redis-redis哨兵集群

Redis Sentinel(哨兵)部署

发表评论

电子邮件地址不会被公开。 必填项已用*标注