前面我们知道如何配置Redis的主从复制,虽然在一定程度解决了数据的冗余备份的问题。但是仅仅是主从复制还不能满足让Redis能提供稳定高效的服务。所以我们需要让Redis具有高可用(High Availability)能力,让我们的系统更加稳健。
Redis高可用其实有很多方式来进行处理,但是在Redis2.6版本后,Redis原生就支持的Sentinel是后面使用最广泛的高可用架构,这样也就很容易的进行构建一个高可用的Redis服务。
本章我们将学习如何来配置Redis的高可用。
&emps;Sentinel翻译为哨兵,它充当了Redis主实例和从实例的守卫者。哨兵要保证高可用,所以它不能仅仅只有一个。在我们的一般的高可用集群中,至少应该存在三个Sentinel才能构建一个高可用的Redis服务。
当多个Sentinel检测到主实例下线后,其中的一个Sentinel进程就会被选举出来负责推选一个从实例替代主实例,整个过程都是系统自动化来进行的(必须保证配置一定要准确)。
要配置一个高可用Redis服务,那么我们至少要满足一主两从的架构。并且至少需要启动三个Sentinel进程来监测主实例是否下线。
IP地址 | 端口 | 角色 |
---|---|---|
192.168.71.108 | 6379 | Master |
192.168.71.105 | 6379 | Slave-1 |
192.168.71.106 | 6379 | Slave-2 |
192.168.71.108 | 26379 | Sentinel-1 |
192.168.71.105 | 26379 | Sentinel-2 |
192.168.71.106 | 26379 | Sentinel-3 |
操作步骤:
1、首先我们要将每个Redis实例的bind后面追加上自己对应服务器的IP地址,如:
bind 127.0.0.1 192.168.71.108 #对应Master
bind 127.0.0.1 192.168.71.105 #对应Slave-1
bind 127.0.0.1 192.168.71.106 #对应Slave-2
2、将Slave-1和Slave-2的配置文件修改如下参数:
slaveof 192.168.71.108 6379
3、然后启动三台Redis实例并在主实例查看主从关系
#启动命令
[root@localhost apps]# ./redis/src/redis-server ./redis/redis.conf
#以下是在Master实例上查看的信息
127.0.0.1:6379> INFO replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.71.105,port=6379,state=online,offset=743,lag=0
slave1:ip=192.168.71.106,port=6379,state=online,offset=743,lag=0
master_replid:62091d9c38bd2cdd215d611bd2fb29e87f2956bd
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:743
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:743
上面确保是两个从实例,表示配置成功。
4、现在我们配置sentinel.conf(配置文件就在redis目录下,我们只需要修改下面的参数即可,这里我们三台redis服务的配置都一样),配置文件内容如下:
# Sentinel节点的端口
port 26379
# 当前Sentinel节点监控 192.168.71.108:6379 这个主节点
# 2代表判断主节点失败至少需要2个Sentinel节点节点同意
# mymaster是主节点的别名
sentinel monitor mymaster 192.168.71.108 6379 2
# 每个Sentinel节点都要定期PING命令来判断Redis数据节点和其余Sentinel节点是否可达,如果超过30000毫秒且没有回复,则判定不可达
sentinel down-after-milliseconds mymaster 30000
# 当Sentinel节点集合对主节点故障判定达成一致时,Sentinel领导者节点会做故障转移操作,选出新的主节点,原来的从节点会向新的主节点发起复制操作,限制每次向新的主节点发起复制操作的从节点个数为1
sentinel parallel-syncs mymaster 1
# 故障转移超时时间为180000毫秒
sentinel failover-timeout mymaster 180000
以上的配置算基本配置完成,但是这里会有一个很重要的问题,我们默认情况下protected-mode是yes,如果这配置是yes的状态下,后面测试主节点下线就会不能动态进行切换,所以我的解决方式就是:
protected-mode no
但是这个做法不推荐,其实默认为yes是为了安全着想,那么就需要大家去设置访问密码。参考文档:Redis protected-mode
5、分别在三台服务器上启动Sentinel进程,启动方式有两种
# 方式一
[root@localhost apps]# ./redis/src/redis-server ./redis/sentinel.conf --sentinel
#方式二
[root@localhost apps]# ./redis/src/redis-sentinel ./redis/sentinel.conf
启动的过程中可以观察相关日志,这里就不展示了。从Sentinel-1日志中我们可以看出它成功的检测到从实例和其他哨兵,日志如下:
...
5590:X 02 Sep 17:17:15.841 * +slave slave 192.168.71.105:6379 192.168.71.105 6379 @ mymaster 192.168.71.108 6379
5590:X 02 Sep 17:17:15.844 * +slave slave 192.168.71.106:6379 192.168.71.106 6379 @ mymaster 192.168.71.108 6379
5590:X 02 Sep 17:17:32.066 * +sentinel sentinel 7d459a3a0e2dd2701434d4e878b2b301724d05d7 192.168.71.105 26379 @ mymaster 192.168.71.108 6379
5590:X 02 Sep 17:17:39.476 * +sentinel sentinel e66625d47cad81f781a19fc997013329fdca87b9 192.168.71.106 26379 @ mymaster 192.168.71.108 6379
5590:X 02 Sep 17:18:02.106 # +sdown sentinel 7d459a3a0e2dd2701434d4e878b2b301724d05d7 192.168.71.105 26379 @ mymaster 192.168.71.108 6379
5590:X 02 Sep 17:18:09.537 # +sdown sentinel e66625d47cad81f781a19fc997013329fdca87b9 192.168.71.106 26379 @ mymaster 192.168.71.108 6379
6、在Sentinel-1上执行INFO SENTINEL命令
[root@localhost apps]# ./redis/src/redis-cli -p 26379
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=192.168.71.108:6379,slaves=2,sentinels=3
7、在Sentinel-1上查看sentinel.conf文件的最后几行
[root@localhost apps]# cat redis/sentinel.conf
...
# Generated by CONFIG REWRITE
sentinel known-slave mymaster 192.168.71.105 6379
sentinel known-slave mymaster 192.168.71.106 6379
sentinel known-sentinel mymaster 192.168.71.105 26379 7d459a3a0e2dd2701434d4e878b2b301724d05d7
sentinel current-epoch 0
上面我们配置了Sentinel,但是Sentinel进程是如何检测到从实例和其他哨兵的呢?我们在sentinel.conf的配置文件中只配置了主实例的信息。其实我们可以理解为,为了从实例的信息,Sentinel会向主实例发送INFO REPLICATION命令。就算从实例有很多级,也可以通过递归的方式扫描找到他们。实际上,Sentinel进程每隔10秒钟就会向其监控的所有Redis实例[主实例和所有从实例]发送INFO REPLICATION命令,来获取整个主从复制拓扑结构的最新信息。
那么多个Sentinel进程又是如何进行通信的呢?其实每隔Sentinel进程每2秒钟就会想一个名为sentinel:hello的频道发布一个消息,报告其自身所监控的主实例的状态。所以我们只需要订阅了该频道就可以发现Sentinel的信息了。操作如下:
[root@localhost ~]# /apps/redis/src/redis-cli
127.0.0.1:6379> SUBSCRIBE __sentinel__:hello
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "__sentinel__:hello"
3) (integer) 1
1) "message"
2) "__sentinel__:hello"
3) "192.168.71.106,26379,e66625d47cad81f781a19fc997013329fdca87b9,0,mymaster,192.168.71.108,6379,0"
1) "message"
2) "__sentinel__:hello"
3) "192.168.71.105,26379,7d459a3a0e2dd2701434d4e878b2b301724d05d7,0,mymaster,192.168.71.108,6379,0"
1) "message"
2) "__sentinel__:hello"
3) "192.168.71.108,26379,8c51a4f1a7d7c5634699eb12145f6ffcefee2b3c,0,mymaster,192.168.71.108,6379,0"
1) "message"
2) "__sentinel__:hello"
3) "192.168.71.106,26379,e66625d47cad81f781a19fc997013329fdca87b9,0,mymaster,192.168.71.108,6379,0"
1) "message"
2) "__sentinel__:hello"
3) "192.168.71.105,26379,7d459a3a0e2dd2701434d4e878b2b301724d05d7,0,mymaster,192.168.71.108,6379,0"
1) "message"
2) "__sentinel__:hello"
3) "192.168.71.108,26379,8c51a4f1a7d7c5634699eb12145f6ffcefee2b3c,0,mymaster,192.168.71.108,6379,0"
1) "message"
...
当从实例和其他Sentinel的信息发生改变是,Sentinel的配置文件也会将更新。所以Sentinel进程必须对配置文件有写入权限的原因。
值得注意的就是,如果我们系统使用了Sentinel,就需要客户端支持。在没有使用Sentinel的时候,我们操作Redis主要是连接到主实例,但是在使用功能Sentinel后,如果主实例出现了故障,那么主实例的地址就会改变。要获取最新的主实例的信息,客户端就需要从Sentinel进行查询,这可以通过sentinel get-master-addr-by-name
[root@localhost ~]# /apps/redis/src/redis-cli -p 26379
127.0.0.1:26379> sentinel get-master-addr-by-name mymaster
1) "192.168.71.108"
2) "6379"