由于对Redis的许多概念都有不同的名词解释,所以在介绍RedisSentinel之前,先对几个名词进行说明,这样便于在后面的介绍中达成一致,如表9-1所示。
Redis Sentinel是Redis的高可用实现方案,在实际的生产环境中,对提高整个系统的高可用性是非常有帮助的,
本节首先会回顾主从复制模式下故障处理可能产生的问题,而后引出高可用的概念,最后重点分析Redis Sentinel的基本架构、优势,以及是如何实现高可用的。
Redis的主从复制模式可以将主节点的数据改变同步给从节点,这样从节点就可以起到两个作用:
但是主从复制也带来了以下问题:
其中第一个问题就是Redis的高可用问题,将在下一个小节进行分析。
第二、三个问题属于Redis的分布式问题,会在第10章介绍。
Redis主从复制模式下,一旦主节点出现了故障不可达,需要人工干预进行故障转移,无论对于Redis的应用方还是运维方都带来了很大的不便。
对于应用方来说无法及时感知到主节点的变化,必然会造成一定的写数据丢失和读数据错误,甚至可能造成应用方服务不可用。
对于Redis的运维方来说,整个故障转移的过程是需要人工来介入的,故障转移实时性和准确性上都无法得到保障,图9-1到图9-5展示了一个1主2从的Redis主从复制模式下的主节点出现故障后,是如何进行故障转移的,过程如下所示。
上述处理过程就可以认为整个服务或者架构的设计不是高可用的,因为整个故障转移的过程需要人介入。
考虑到这点,有些公司把上述流程自动化了,但是仍然存在如下问题:
当主节点出现故障时,Redis Sentinel能自动完成故障发现和故障转移,并通知应用方,从而实现真正的高可用。
注意
Redis2.6版本提供Redis Sentinel v1版本,但是功能性和健壮性都有一些问题,如果想使用Redis Sentinel的话,建议使用2.8以上版本,也就是v2版本的Redis Sentinel。
Redis Sentinel是一个分布式架构,其中包含若干个Sentinel节点和Redis数据节点,每个Sentinel节点会对数据节点和其余Sentinel节点进行监控,当它发现节点不可达时,会对节点做下线标识。
如果被标识的是主节点,它还会和其他Sentinel节点进行“协商”,当大多数Sentinel节点都认为主节点不可达时,
它们会选举出一个Sentinel节点来完成自动故障转移的工作,同时会将这个变化实时通知给Redis应用方。
整个过程完全是自动的,不需要人工来介入,所以这套方案很有效地解决了Redis的高可用问题。
注意
这里的分布式是指:Redis数据节点、Sentinel节点集合、客户端分布在多个物理节点的架构,不要与第10章介绍的Redis Cluster分布式混淆。
如图9-6所示,Redis Sentinel与Redis主从复制模式只是多了若干Sentinel节点,所以Redis Sentinel并没有针对Redis节点做了特殊处理,这里是很多开发和运维人员容易混淆的。
从逻辑架构上看,Sentinel节点集合会定期对所有节点进行监控,特别是对主节点的故障实现自动转移。
下面以1个主节点、2个从节点、3个Sentinel节点组成的Redis Sentinel为例子进行说明,拓扑结构如图9-7所示。
整个故障转移的处理逻辑有下面4个步骤:
2) 如图9-9所示,每个Sentinel节点通过定期监控发现主节点出现了故障。
4) 如图9-11所示,Sentinel领导者节点执行了故障转移,整个过程和9.1.2节介绍的是完全一致的,只不过是自动化完成的。
通过上面介绍的Redis Sentinel逻辑架构以及故障转移的处理,可以看出Redis Sentinel具有以下几个功能:
同时看到,Redis Sentinel包含了若个Sentinel节点,这样做也带来了两个好处:
但是Sentinel节点本身就是独立的Redis节点,只不过它们有一些特殊,它们不存储数据,只支持部分命令。
下一节将完整介绍Redis Sentinel的部署过程,相信在安装和部署完Redis Sentinel后,读者能更清晰地了解Redis Sentinel的整体架构。
上一节介绍了Redis Sentinel的基本架构,本节将介绍如何安装和部署Redis Sentinel。
下面将以3个Sentinel节点、1个主节点、2个从节点组成一个RedisSentinel进行说明,拓扑结构如图9-13所示。
具体的物理部署如表9-2所示。
9.1节提到过,Redis Sentinel中Redis数据节点没有做任何特殊配置,按照之前章节介绍的方法启动就可以,下面以一个比较简单的配置进行说明。
配置:
redis-6379.conf port 6379 daemonize yes logfile "6379.log" dbfilename "dump-6379.rdb" dir "/opt/soft/redis/data/"
启动主节点:
redis-server redis-6379.conf
确认是否启动。一般来说只需要ping命令检测一下就可以,确认Redis数据节点是否已经启动。
$ redis-cli -h 127.0.0.1 -p 6379 ping PONG
此时拓扑结构如图9-14所示。
2.启动两个从节点
配置:
两个从节点的配置是完全一样的,下面以一个从节点为例子进行说明,和主节点的配置不一样的是添加了slaveof配置。
redis-6380.conf port 6380 daemonize yes logfile "6380.log" dbfilename "dump-6380.rdb" dir "/opt/soft/redis/data/" slaveof 127.0.0.1 6379
启动两个从节点:
redis-server redis-6380.conf redis-server redis-6381.conf
验证:
$ redis-cli -h 127.0.0.1 -p 6380 ping PONG $ redis-cli -h 127.0.0.1 -p 6381 ping PONG
主节点的视角,它有两个从节点,分别是127.0.0.1:6380和127.0.0.1:6381:
$ redis-cli -h 127.0.0.1 -p 6379 info replication # Replication role:master 490 connected_slaves:2 slave0:ip=127.0.0.1,port=6380,state=online,offset=281,lag=1 slave1:ip=127.0.0.1,port=6381,state=online,offset=281,lag=0 .................
从节点的视角,它的主节点是127.0.0.1:6379:
$ redis-cli -h 127.0.0.1 -p 6380 info replication # Replication role:slave master_host:127.0.0.1 master_port:6379 master_link_status:up .................
此时拓扑结构如图9-15所示。
3个Sentinel节点的部署方法是完全一致的(端口不同),下面以sentinel-1节点的部署为例子进行说明。
redis-sentinel-26379.conf port 26379 daemonize yes logfile "26379.log" dir /opt/soft/redis/data 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
Sentinel节点的启动方法有两种: 方法一,使用redis-sentinel命令:
redis-sentinel redis-sentinel-26379.conf
方法二,使用redis-server命令加--sentinel参数:
redis-server redis-sentinel-26379.conf --sentinel
两种方法本质上是一样的。
Sentinel节点本质上是一个特殊的Redis节点,所以也可以通过info命令来查询它的相关信息,从下面info的Sentinel片段来看,Sentinel节点找到了主节点127.0.0.1:6379,发现了它的两个从节点,同时发现Redis Sentinel一共有3个Sentinel节点。
这里只需要了解Sentinel节点能够彼此感知到对方,同时能够感知到Redis数据节点就可以了:
$ redis-cli -h 127.0.0.1 -p 26379 info Sentinel # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 master0:name=mymaster,status=ok,address=127.0.0.1:6379,slaves=2,sentinels=3
当三个Sentinel节点都启动后,整个拓扑结构如图9-16所示。
至此Redis Sentinel已经搭建起来了,整体上还是比较容易的,但是有2点需要强调一下:
了解每个配置的含义有助于更加合理地使用Redis Sentinel,因此本节将对每个配置的使用和优化进行详细介绍。
Redis安装目录下有一个sentinel.conf,是默认的Sentinel节点配置文件,下面就以它作为例子进行说明。
port 26379 dir /opt/soft/redis/data 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 #sentinel auth-pass <master-name> <password> #sentinel notification-script <master-name> <script-path> #sentinel client-reconfig-script <master-name> <script-path> port和dir分别代表Sentinel节点的端口和工作目录,下面重点对sentinel相
关配置进行详细说明。
sentinel monitor <master-name> <ip> <port> <quorum>
Sentinel节点会定期监控主节点,所以从配置上必然也会有所体现,
但实际上Sentinel节点会对所有节点进行监控,但是在Sentinel节点的配置中没有看到有关从节点和其余Sentinel节点的配置,那是因为Sentinel节点会从主节点中获取有关从节点以及其余Sentinel节点的相关信息,有关这部分是如何实现的,将在9.5节介绍。
例如某个Sentinel初始节点配置如下:
port 26379 daemonize yes logfile "26379.log" dir /opt/soft/redis/data 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
当所有节点启动后,配置文件中的内容发生了变化,体现在三个方面:
port 26379 daemonize yes logfile "26379.log" dir "/opt/soft/redis/data" sentinel monitor mymaster 127.0.0.1 6379 2 sentinel config-epoch mymaster 0 sentinel leader-epoch mymaster 0 #发现两个slave节点 sentinel known-slave mymaster 127.0.0.1 6380 sentinel known-slave mymaster 127.0.0.1 6381 #发现两个sentinel节点 sentinel known-sentinel mymaster 127.0.0.1 26380 282a70ff56c36ed56e8f7ee6ada741 24140d6f53 sentinel known-sentinel mymaster 127.0.0.1 26381 f714470d30a61a8e39ae031192f1fe ae7eb5b2be sentinel current-epoch 0 496
quorum 参数用于故障发现和判定,例如将quorum配置为2,代表至少有2个Sentinel节点认为主节点不可达,那么这个不可达的判定才是客观的。
对于quorum 设置的越小,那么达到下线的条件越宽松,反之越严格。
一般建议将其设置为Sentinel节点的一半加1。同时quorum还与Sentinel节点的领导者选举有关,至少要有 max(quorum,num(sentinels)/2+1)个Sentinel节点参与选举,才能选出领导者Sentinel,从而完成故障转移。
例如有5个Sentinel节点,quorum=4,那么至少要有max(quorum,num(sentinels)/2+1)=4个在线Sentinel节点才可以进行领导者选举。
配置如下:
sentinel down-after-milliseconds <master-name> <times>
每个Sentinel节点都要通过定期发送ping命令来判断Redis数据节点和其余Sentinel节点是否可达,如果超过了down-after-milliseconds配置的时间且没有有效的回复,则判定节点不可达, times(单位为毫秒)就是超时时间。
这个配置是对节点失败判定的重要依据。优化说明:
down-after-milliseconds越大,代表Sentinel节点对于节点不可达的条件越宽松,反之越严格。 条件宽松有可能带来的问题是节点确实不可达了,那么应用方需要等待故障转移的时间越长, 也就意味着应用方故障时间可能越长。 条件严格虽然可以及时发现故障完成故障转移,但是也存在一定的误判率。
运维提示
down-after-milliseconds虽然以 master-name 为参数,但实际上对 Sentinel节点、主节点、从节点的失败判定同时有效。
配置如下:
sentinel parallel-syncs <master-name> <nums>
当Sentinel节点集合对主节点故障判定达成一致时,Sentinel领导者节点会做故障转移操作,选出新的主节点,原来的从节点会向新的主节点发起复制操作,parallel-syncs就是用来限制在一次故障转移之后,每次向新的主节 点发起复制操作的从节点个数。
如果这个参数配置的比较大,那么多个从节点会向新的主节点同时发起复制操作,尽管复制操作通常不会阻塞主节点,
但是同时向主节点发起复制,必然会对主节点所在的机器造成一定的网络和磁盘IO开销。
图9-17展示parallel-syncs=3和parallel-syncs=1的效果,parallelsyncs=3会同时发起复制parallel-syncs=1时从节点会轮询发起复制。
配置如下:
sentinel failover-timeout <master-name> <times>
failover-timeout通常被解释成故障转移超时时间,但实际上它作用于故障转移的各个阶段:
failover-timeout的作用具体体现在四个方面:
配置如下:
sentinel auth-pass <master-name> <password>
如果Sentinel监控的主节点配置了密码,sentinel auth-pass配置通过添加主节点的密码,防止Sentinel节点对主节点无法监控。
配置如下:
sentinel notification-script <master-name> <script-path>
sentinel notification-script的作用是在故障转移期间,当一些警告级别的Sentinel事件发生(指重要事件,例如-sdown:客观下线、-odown:主观下线)时,会触发对应路径的脚本,并向脚本发送相应的事件参数。
例如在/opt/redis/scripts/下配置了notification.sh,该脚本会接收每个Sentinel节点传过来的事件参数,可以利用这些参数作为邮件或者短信报警依据:
#!/bin/sh #获取所有参数 msg=$* #报警脚本或者接口,将msg作为参数 exit 0
如果需要该功能,就可以在Sentinel节点添加如下配置(<mastername>=mymaster):
sentinel notification-script mymaster /opt/redis/scripts/notification.sh
例如下面就是某个Sentinel节点对主节点做了主观下线(有关主观下线的概念将在9.5节进行详细介绍)后脚本收到的参数:
配置如下:
sentinel client-reconfig-script <master-name> <script-path>
sentinel client-reconfig-script的作用是在故障转移结束后,会触发对应路径的脚本,并向脚本发送故障转移结果的相关参数。
和notification-script类似,可以在/opt/redis/scripts/下配置了client-reconfig.sh,该脚本会接收每个Sentinel节点传过来的故障转移结果参数,并触发类似短信和邮件报警:
#!/bin/sh #获取所有参数 msg=$* #报警脚本或者接口,将msg作为参数 exit 0
如果需要该功能,就可以在Sentinel节点添加如下配置(<mastername>=mymaster):
sentinel client-reconfig-script mymaster /opt/redis/scripts/client-reconfig.sh
当故障转移结束,每个Sentinel节点会将故障转移的结果发送给对应的脚本,具体参数如下:
<master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
例如以下内容分别是三个Sentinel节点发送给脚本的,其中一个是leader,另外两个是observer:
mymaster leader start 127.0.0.1 6379 127.0.0.1 6380 mymaster observer start 127.0.0.1 6379 127.0.0.1 6380 mymaster observer start 127.0.0.1 6379 127.0.0.1 6380
有关sentinel notification-script和sentinel client-reconfig-script有几点需要注意:
Redis Sentinel可以同时监控多个主节点,具体拓扑图类似于图9-18。
配置方法也比较简单,只需要指定多个masterName来区分不同的主节点即可,例如下面的配置监控monitor master-business-1(10.10.xx.1:6379)和 monitor master-business-2(10.10.xx.2:6379)两个主节点:
sentinel monitor master-business-1 10.10.xx.1 6379 2 sentinel down-after-milliseconds master-business-1 60000 sentinel failover-timeout master-business-1 180000 sentinel parallel-syncs master-business-1 1 sentinel monitor master-business-2 10.16.xx.2 6380 2 sentinel down-after-milliseconds master-business-2 10000 sentinel failover-timeout master-business-2 180000 sentinel parallel-syncs master-business-2 1
和普通的Redis数据节点一样,Sentinel节点也支持动态地设置参数,而且和普通的Redis数据节点一样并不是支持所有的参数,具体使用方法如下:
sentinel set <param> <value>
有几点需要注意一下:
到现在有关Redis Sentinel的配置和部署方法相信读者已经基本掌握了,但在实际生产环境中都有哪些部署的技巧?本节将总结一下。
Sentinel节点不应该部署在一台物理“机器”上。
这里特意强调物理机是因为一台物理机做成了若干虚拟机或者现今比较流行的容器,它们虽然有不同的IP地址,但实际上它们都是同一台物理机, 同一台物理机意味着如果这台机器有什么硬件故障,所有的虚拟机都会受到影响,为了实现Sentinel节点集合真正的高可用,请勿将Sentinel节点部署在同一台物理机器上。
部署至少三个且奇数个的Sentinel节点。 3个以上是通过增加Sentinel节点的个数提高对于故障判定的准确性,因为领导者选举需要至少一半加1个节点,奇数个节点可以在满足该条件的基础上节省一个节点。 有关Sentinel节点如何判断节点失败,如何选举出一个Sentinel节点进行故障转移将在9.5节进行介绍。
只有一套Sentinel,还是每个主节点配置一套Sentinel? Sentinel节点集合可以只监控一个主节点,也可以监控多个主节点,也就意味着部署拓扑可能是图9-19和图9-20两种情况。
那么在实际生产环境中更偏向于哪一种部署方式呢,下面分别分析两种方案的优缺点。
运维提示
如果Sentinel节点集合监控的是同一个业务的多个主节点集合,那么使用方案一、否则一般建议采用方案二。
Sentinel节点是一个特殊的Redis节点,它有自己专属的API,本节将对其进行介绍。
为了方便演示,以图9-21进行说明:Sentinel节点集合监控着两组主从模式的Redis数据节点。
展示所有被监控的主节点状态以及相关的统计信息,例如:
图9-21 一套Sentinel集合监控多个主从结构
127.0.0.1:26379> sentinel masters 1) 1) "name" 2) "mymaster-2" 3) "ip" 4) "127.0.0.1" 5) "port" 6) "6382" .........忽略............ 2) 1) "name" 2) "mymaster-1" 3) "ip" 4) "127.0.0.1" 5) "port" 6) "6379" .........忽略............
展示指定 master name 的主节点状态以及相关的统计信息,例如:
127.0.0.1:26379> sentinel master mymaster-1 1) "name" 2) "mymaster-1" 3) "ip" 4) "127.0.0.1" 5) "port" 6) "6379" .........忽略............
展示指定master name 的从节点状态以及相关的统计信息,例如:
127.0.0.1:26379> sentinel slaves mymaster-1 1) 1) "name" 2) "127.0.0.1:6380" 3) "ip" 4) "127.0.0.1" 5) "port" 6) "6380" .........忽略............ 2) 1) "name" 2) "127.0.0.1:6381" 3) "ip" 4) "127.0.0.1" 5) "port" 6) "6381" .........忽略............
展示指定 master name 的Sentinel节点集合(不包含当前Sentinel节点),例如:
127.0.0.1:26379> sentinel sentinels mymaster-1 1) 1) "name" 2) "127.0.0.1:26380" 3) "ip" 4) "127.0.0.1" 5) "port" 6) "26380" .........忽略............ 2) 1) "name" 2) "127.0.0.1:26381" 3) "ip" 4) "127.0.0.1" 5) "port" 6) "26381" .........忽略............
返回指定 master name 主节点的IP地址和端口,例如:
127.0.0.1:26379> sentinel get-master-addr-by-name mymaster-1 1) "127.0.0.1" 2) "6379"
当前Sentinel节点对符合 pattern(通配符风格)主节点的配置进行重置,包含清除主节点的相关状态(例如故障转移),重新发现从节点和Sentinel节点。
例如sentinel-1节点对mymaster-1节点重置状态如下:
127.0.0.1:26379> sentinel reset mymaster-1 (integer) 1
对指定 master name 主节点进行强制故障转移(没有和其他Sentinel节点“协商”),当故障转移完成后,其他Sentinel节点按照故障转移的结果更新自身配置,这个命令在Redis Sentinel的日常运维中非常有用,将在9.6节进行详细介绍。
例如,对mymaster-2进行故障转移:
127.0.0.1:26379> sentinel failover mymaster-2 OK
执行命令前,mymaster-2是127.0.0.1:6382
127.0.0.1:26379> info sentinel # Sentinel sentinel_masters:2 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 master0:name=mymaster-2,status=ok,address=127.0.0.1:6382,slaves=2,sentinels=3 master1:name=mymaster-1,status=ok,address=127.0.0.1:6379,slaves=2,sentinels=3
执行命令后:mymaster-2由原来的一个从节点127.0.0.1:6383代替。
127.0.0.1:26379> info sentinel # Sentinel sentinel_masters:2 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 master0:name=mymaster-2,status=ok,address=127.0.0.1:6383,slaves=2,sentinels=3 master1:name=mymaster-1,status=ok,address=127.0.0.1:6379,slaves=2,sentinels=3
检测当前可达的Sentinel节点总数是否达到 quorum 的个数。例如quorum=3,而当前可达的Sentinel节点个数为2个,那么将无法进行故障转移,Redis Sentinel的高可用特性也将失去。
例如:
127.0.0.1:26379> sentinel ckquorum mymaster-1 OK 3 usable Sentinels. Quorum and failover authorization can be reached
将Sentinel节点的配置强制刷到磁盘上,这个命令Sentinel节点自身用得比较多,对于开发和运维人员只有当外部原因(例如磁盘损坏)造成配置文件损坏或者丢失时,这个命令是很有用的。
例如:
127.0.0.1:26379> sentinel flushconfig OK
取消当前Sentinel节点对于指定 master name 主节点的监控。
例如sentinel-1当前对mymaster-1进行了监控:
127.0.0.1:26379> info sentinel # Sentinel sentinel_masters:2 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 master0:name=mymaster-2,status=ok,address=127.0.0.1:6382,slaves=2,sentinels=3 master1:name=mymaster-1,status=ok,address=127.0.0.1:6379,slaves=2,sentinels=3
例如下面,sentinel-1节点取消对mymaster-1节点的监控,但是要注意这个命令仅仅对当前Sentinel节点有效。
127.0.0.1:26379> sentinel remove mymaster-1 OK
再执行info sentinel命令,发现sentinel-1已经失去对mymaster-1的监控:
127.0.0.1:26379> info sentinel # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 master0:name=mymaster-2,status=ok,address=127.0.0.1:6383,slaves=2,sentinels=3
这个命令和配置文件中的含义是完全一样的,只不过是通过命令的形式来完成Sentinel节点对主节点的监控。
例如命令sentinel-1节点重新监控mymaster-1节点:
127.0.0.1:26379> sentinel monitor mymaster-1 127.0.0.1 6379 2 OK
命令执行后,发现sentinel-1节点重新对mymaster-1节点进行监控:
# Sentinel sentinel_masters:2 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 master0:name=mymaster-2,status=ok,address=127.0.0.1:6383,slaves=2,sentinels=3 master1:name=mymaster-1,status=ok,address=127.0.0.1:6379,slaves=2,sentinels=3
动态修改Sentinel节点配置选项,这个命令已经在9.2.4小节进行了说明,这里就不赘述了。
Sentinel节点之间用来交换对主节点是否下线的判断,根据参数的不同,还可以作为Sentinel领导者选举的通信方式,具体细节9.5节会介绍。
本文作者:Eric
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!