前言
redis的主从复制在前面的文章已经详细地了解过了,本文主要是针对主从切换的方案来说一下。一种很熟悉的应用场景,加入master的服务器突然间岩机的时候,那么对于整个的系统都是不能写数据(master主要负责写),所以系统就相当于已经瘫痪。如果可以自动地在master发生故障时,能够故障转移(failover),将其中一个slave推荐成为master。基于redis的官方的sentinel(哨兵)就可以实现这种方案。
sentinel的简介
Redis-sentinel是Redis实例的监控管理、通知和实例失效备援服务,是Redis集群的管理工具。在一般的分布式中心节点数据库中,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 的主观下线状态就会被移除。
主观下线和客观下线
主观下线:Subjectively Down,简称 SDOWN,指的是当前 Sentinel 实例对某个redis服务器做出的下线判断。
客观下线:Objectively Down, 简称 ODOWN,指的是多个 Sentinel 实例在对Master Server做出 SDOWN 判断,并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后,得出的Master Server下线判断,然后开启failover.
SDOWN适合于Master和Slave,只要一个 Sentinel 发现Master进入了ODOWN, 这个 Sentinel 就可能会被其他 Sentinel 推选出, 并对下线的主服务器执行自动故障迁移操作。
ODOWN只适用于Master,对于Slave的 Redis 实例,Sentinel 在将它们判断为下线前不需要进行协商, 所以Slave的 Sentinel 永远不会达到ODOWN。
sentinel.conf配置:
1:指定监听Master(2个节点)
port 26379
daemonize yes
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 900000
#上面配置文件说明如下:
#第一行指定sentinel端口号
#第二行指定sentinel为后台启动
#第三行指定Sentinel去监视一个名为 mymaster 的Master,Master的IP地址为127.0.0.1,端口号为6379,最后的2表示当有2个Sentinel检测到Master异常时才会判定其失效,即只有当2个Sentinel都判定Master失效了才会自动迁移,如果Sentinel的数量不达标,则不会执行自动故障迁移。
#第四行指定Sentinel判定Master断线的时间。(单位为毫秒,判定为主观下线SDOWN)
#第五行指定在执行故障转移时,最多可以有多少个Slave同时对新的Master进行同步。这个数字设置为1,虽然完成故障转移所需的时间会变长,但是可以保证每次只有1个Slave处于不能处理命令请求的状态、
模拟测试
1、分别启动三个redis实例
(1)127.0.0.1 6379 (master)
(2)127.0.0.1 6380(slave)
(3)127.0.0.1 6381 (slave)
每一个实例对应着一个不同的redis.conf文件,master的redis.conf基本不用改。slave主要是修改
<pre name="code" class="html">port 6380
slaveof 127.0.0.1 6379
port 6381
slaveof 127.0.0.1 6379
每一个slave的实例都配置slaveof。
启动redis,进入到redis的文件夹下面
redis-server redis.conf
再打开终端
连接master,端口6379
设置一个键值 name='huangzengbing‘
查看复制信息
可以看到6379是一个master 的角色,其中属于他的slave有两个,分别是6380和6381
再打开另一个终端,连接6380
获取键名为name的值,之前在master设置的。可以看到在6380的这个slave上已经有了这个值,说明主从复制成功。
在看一下6380的复制信息
可以看到6380是slave的角色,对应的master是在线的
再打开一个终端,连接6381
获取键名为name的值,可以看到存在这个值,说明主从复制成功
在看一下复制信息
角色为slave,对应着master的信息
以上的测试,可以知道master-slave的复制成功。
模拟failover—故障转移
分别启动两个sentinel实例,端口分别对应26379和26380,sentinel.conf的配置
port 26379
daemonize yes
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 900000
例外一个sentinel.conf
port 26380
daemonize yes
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 900000
下面启动sentinel,端口26379
注意redis-sentinel这个执行文件是存放在下载的redis的包里的。
启动另一个sentinel,端口26380
下面模拟master出现故障。模拟方案是将master突然关闭掉,在6379的终端上关闭redis实例。
关闭之后,在get name,无法在获取到值。
接着,查看6380的复制信息
可以看到,6380已经成了master的角色,他的slave只有一个6381
在查看6381的复制信息
可以看到6381对应的master是6380,而不是6379(因为它已关闭),说明了什么呢?
再给新的master 6380设置值,看看slave 6381是否同步
在6381上获取键名为address的值
可以看到能够获取到值。说明新建立的主从关系能够实现主从复制。
下面重新启动6379的redis实例
查看复制信息
可以看到,6379已经成为了6380的slave。
获取健名为address的值
6379可以获取到master的设置的值,说明重新启动的slave可以实现复制
再查看一下6379的对应的redis.conf的配置文件
配置文件rewrite(重写)一个新的配置项,标志master是6380
而在查看6380的对应的redis.conf,已经将salveof 127.0.0.1 6379 这一个配置删除,因为它已经成为了新的master了,无需配置slaveof。
模拟测试总结与问题
(1)redis的sentinel提供了一个很好的HA方案,但就目前来说,该方案还没有合并进正式版本中,要在实际生产环境使用的话,可能还需要配合客户端。
(2)客户端如何动态的获取sentinel的信息,如何动态实现主从切换。