Redis-③哨兵模式(Sentinel)

1,663 阅读9分钟

一、哨兵模式概述

哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。

这里的哨兵有两个作用

  • 通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。
  • 当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。

然而一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。
用文字描述一下故障切换(failover)的过程。假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象成为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线。这样对于客户端而言,一切都是透明的。

二、Redis配置哨兵模式

下面以配置1主2从3哨兵的Redis服务器来演示这个过程。
准备3个服务器:192.168.11.128、192.168.11.129、192.168.11.130

服务类型是否是主服务器IP地址端口
Redis192.168.11.12830001
Redis192.168.11.12930002
Redis192.168.11.13030003
Sentinel-192.168.11.12830004
Sentinel-192.168.11.12930005
Sentinel-192.168.11.13030006

首先配置Redis的主、从服务器,修改redis.conf文件如下

# 使得Redis服务器可以跨网络访问
bind 0.0.0.0
# 关闭保护模式
protected-mode no
# 设置密码
requirepass "123456"


# 「从服务器配置」指定主服务器,注意:有关slaveof的配置只是配置从服务器,主服务器不需要配置
slaveof 192.168.11.128 30001
# 「从服务器配置」主服务器密码,注意:有关slaveof的配置只是配置从服务器,主服务器不需要配置
masterauth 123456

上述内容主要是配置Redis服务器,从服务器比主服务器多一个slaveof的配置和密码。
配置3个哨兵,每个哨兵的配置都是一样的。在Redis源码目录下有一个sentinel.conf文件,copy一份进行修改

注意 sentinel auth-pass配置必须放在sentinel monitor后面

# 禁止保护模式
protected-mode no
port 30004
daemonize yes
pidfile /var/run/redis-sentinel-30004.pid
logfile 30004.log

# 配置监听的主服务器,这里sentinel monitor代表监控,mymaster代表服务器的名称,可以自定义,192.168.11.128代表监控的主服务器,6380代表端口,2代表只有两个或两个以上的哨兵认为主服务器不可用的时候,才会进行failover操作。
sentinel monitor mymaster 47.114.60.192 30001 2

# sentinel author-pass定义服务的密码,mymaster是服务名称,123456是Redis服务器密码
# sentinel auth-pass <master-name> <password>
# 注意 此配置必须放在sentinel monitor后面
sentinel auth-pass mymaster 123456

上述关闭了保护模式,便于测试。
有了上述的修改,可以进入Redis的安装目录的src目录,通过下面的命令启动服务器和哨兵

# 启动Redis服务器进程
./redis-server redis.conf
# 启动哨兵进程
./redis-sentinel sentinel-30004.conf
./redis-sentinel sentinel-30005.conf
./redis-sentinel sentinel-30006.conf

注意启动的顺序。**首先是主的Redis服务进程,然后启动从机的服务进程,最后启动3个哨兵的服务进程。**启动后可以看到一下进程:

[root@iZbp1drlwuro5gyrg5l70qZ redis-sentinel]# ps -ef | grep redis
root      2883 11548  0 15:01 pts/0    00:00:00 grep --color=auto redis
root     12849     1  0 14:51 ?        00:00:01 /usr/local/redis/bin/redis-server 0.0.0.0:30001
root     12854     1  0 14:51 ?        00:00:01 /usr/local/redis/bin/redis-server 0.0.0.0:30002
root     12859     1  0 14:51 ?        00:00:01 /usr/local/redis/bin/redis-server 0.0.0.0:30003
root     12864     1  0 14:51 ?        00:00:01 /usr/local/redis/bin/redis-sentinel *:30004 [sentinel]
root     12869     1  0 14:51 ?        00:00:01 /usr/local/redis/bin/redis-sentinel *:30005 [sentinel]
root     12874     1  0 14:51 ?        00:00:01 /usr/local/redis/bin/redis-sentinel *:30006 [sentinel]

一键启动脚本

如果感觉上述步骤过于繁琐, 可使用下面的脚本,在单个服务器上一键创建哨兵模式的6个节点:

#!/bin/bash
# redis-server命令行所在位置
CMD_PATH=/usr/local/redis/bin
PWD=123456
MASTER_IP=47.114.60.192

echo "正在启动主从节点..."
MASTER_PORT=30001
${CMD_PATH}/redis-server --port $MASTER_PORT --bind 0.0.0.0 --protected-mode no --masterauth $PWD  --requirepass $PWD --appendonly yes --appendfilename appendonly-${MASTER_PORT}.aof --dbfilename dump-${MASTER_PORT}.rdb --logfile ${MASTER_PORT}.log --daemonize yes
PORT=30002
${CMD_PATH}/redis-server --port $PORT --bind 0.0.0.0 --protected-mode no --masterauth $PWD  --requirepass $PWD --slaveof $MASTER_IP $MASTER_PORT --appendonly yes --appendfilename appendonly-${PORT}.aof --dbfilename dump-${PORT}.rdb --logfile ${PORT}.log --daemonize yes
PORT=30003
${CMD_PATH}/redis-server --port $PORT --bind 0.0.0.0 --protected-mode no --masterauth $PWD  --requirepass $PWD --slaveof $MASTER_IP $MASTER_PORT --appendonly yes --appendfilename appendonly-${PORT}.aof --dbfilename dump-${PORT}.rdb --logfile ${PORT}.log --daemonize yes
echo "正在启动哨兵节点..."
PORT=30004
${CMD_PATH}/redis-sentinel sentinel-${PORT}.conf
PORT=30005
${CMD_PATH}/redis-sentinel sentinel-${PORT}.conf
PORT=30006
${CMD_PATH}/redis-sentinel sentinel-${PORT}.conf
echo ">>>启动完成<<<"
echo "查看redis进程:"
ps -aux | grep redis

一键停止脚本

一键关闭哨兵模式的6个节点

#!/bin/bash
CMD_PATH=/usr/local/redis/bin
PWD=123456

echo "正在关闭主从及哨兵节点..."
${CMD_PATH}/redis-cli -p 30001 -a $PWD shutdown save
${CMD_PATH}/redis-cli -p 30002 -a $PWD shutdown save
${CMD_PATH}/redis-cli -p 30003 -a $PWD shutdown save
${CMD_PATH}/redis-cli -p 30004 -a $PWD shutdown save
${CMD_PATH}/redis-cli -p 30005 -a $PWD shutdown save
${CMD_PATH}/redis-cli -p 30006 -a $PWD shutdown save
echo "正在清理日志..."
rm -rf *.log

echo "正在清理持久化文件AOF&RDB..."
rm -rf dump*.rdb
rm -rf appendonly*.aof
echo "清理完成..."
echo "查看redis进程:"
ps -aux | grep redis

三、项目中配置哨兵模式

修改项目的application.yml配置文件,修改redis的配置:
sentinels中的ip为哨兵服务器的ip+端口

# 哨兵模式
redis.type=s
redis.master=mymaster
redis.sentinels=47.114.60.192:30004,47.114.60.192:30005,47.114.60.192:30006
redis.password=123456
redis.value-serializer=json
redis.database=5

四、验证

验证master

使用命令行cli  或redis客户端 连接master节点,在命令行中执行info replication命令, 验证主从关系

[root@iZbp1drlwuro5gyrg5l70qZ bin]# ./redis-cli -p 30001 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:30001> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=47.114.60.192,port=30002,state=online,offset=138,lag=0
slave1:ip=47.114.60.192,port=30003,state=online,offset=138,lag=0
master_replid:825e95800e384251627fb2494e5e0fa557a7e2e1
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:138
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:138

验证sentinel

使用命令行cli  或redis客户端 连接任一sentinel节点,在命令行中执行info sentinel命令, 验证sentinel状态 :「master0:name=mymaster,status=ok,address=47.114.60.192:30001,slaves=2,sentinels=3」

[root@iZbp1drlwuro5gyrg5l70qZ bin]# ./redis-cli -p 30004 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:30004> 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=47.114.60.192:30001,slaves=2,sentinels=3

问题

问题描述

Redis Sentinel集群部署的master节点status=sdown

  • 解决问题

哨兵通过三个定时任务做心跳检测:

  1. 每隔10s向主从节点发送info
  2. 每隔2秒向redis数据节点频道发送消息
  3. 每隔1秒,每个Sentinel节点会向主节点、从节点、其余Sentinel节点发送一条ping命令做一次心跳检测,来确认这些节点当前是否可达

其中第1和第2条需要连接客户端。
连接客户端需要保证:

  1. bind的配置中存在ip(已注释)
  2. 确保所有的端口可以访问(防火墙已关闭)
  3. auth节点认证信息(sentinel auth-pass mymaster 123456)

问题描述

启动哨兵节点报错:

FATAL CONFIG FILE ERROR
Reading the configuration file, at line 104
'sentinel auth-pass mymaster redis'
No such master with specified name.
  • 解决问题

检查配置顺序:注意 sentinel auth-pass配置必须放在sentinel monitor后面

sentinel monitor mymaster 47.114.60.192 30001 2

# 注意 此配置必须放在sentinel monitor后面
sentinel auth-pass mymaster 123456

问题描述

Redis的哨兵模式的主从关系连接不成功,但是找不到原因,就用>info replication查看了主从配置的信息

master的配置信息如下:

192.168.1.102:6380> info replication
Replication

role:master
connected_slaves:0 ==》没有连接上任何的slaves连接上该master
master_replid:815c30c336f228220c9d2e7eacb3c1f45c250544
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

slaves的配置信息如下:

192.168.1.102:6382> info replication

Replication

role:slave
master_host:192.168.1.102
master_port:6382  ==》连接的时自己slaves配置端口号6382,不是master的端口号6380,因此主从连接不成功。
master_link_status:down ==》这个时down,并不是up,表示主从并没有连接上
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_repl_offset:1
master_link_down_since_seconds:1532665454
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:0e6b8db9f591f8f93e9c7800e22f8e2dc1afc44e
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

由上述查看的信息发现redis.conf的从配置文件端口号配置错误导致主从连接错误,在从配置的redis.conf下更改为主的端口号就可以了。

slaveof 192.168.1.102 6380

同时查看一下哨兵的配置文件sentinel.conf里面的

sentinel monitor mymaster 192.168.1.102 6380 2

是否也配置错误,要配置成主的端口号才可以

如果出现上述情况,查看日志的时候会发先报下面错误,如果出现可以按照上面的方式进行检查并进行修改

Non blocking connect for SYNC fired the event.

Master replied to PING, replication can continue...
Partial resynchronization not possible (no cached master)
Master is currently unable to PSYNC but should be in the future: -NOMASTERLINK Can't SYNC while not connected with my master