redis的主从搭建与sentinel高可用服务的搭建

  以下内容是记录在公司的测试服务器上安装redis 3.0.7并搭建主从和配置了sentinel服务的过程,验证了一遍当redis主实例宕机后是否会发生主库自动转移,并探究了在故障转移过程中redis实例和sentinel的配置文件的相关参数变化,体会sentinel监控主从、保证主库高可用的基本过程。

 

主从搭建

  在测试服务器P2P-test1(10.19.62.2)上已安装好redis-3.0.7,安装目录为/home/wwwad/software/redis-3.0.7/,test1服务器上只配置了一个redis实例,相关基本配置信息如下:

    端口号为6999(没有采用redis默认的6379端口号);

    datadir为”/data/redis/6999/”;

    安装目录为”/data/redis/6999/bin/”;

    配置文件为”/etc/redis/6999.conf”;

    日志文件为”/etc/redis/6999/redis_6999.log”

 

  在测试服务器test_3(10.19.110.150)上也安装了redis-3.0.7,安装目录为/home/wwwad/redis-3.0.7/目录,test_3服务器上只配置了一个redis实例,相关基本配置信息如下:

    端口号为6999(没有采用redis默认的6379端口号);

    datadir为”/data/redis/6999/”;

    安装目录为”/data/redis/6999/bin/”;

      配置文件为”/etc/redis/6999.conf”;

      日志文件为”/etc/redis/6999/redis_6999.log”

 

开始搭建主从

  我们让10.19.62.2:6999成为主库,10.19.110.150:6999成为从库。搭建主从很简单,最简单地就是进入test_3的redis上,执行”slaveof 10.19.62.2 6999″即建立了主从,如图:

 

  执行info replication命令可以看到role为slave,表示本实例为从库。同样地,可以到10.19.62.2上执行相应的命令查看一下:

  这种通过命令行搭建起来的主从架构是不稳定的。当主从断开或者主从重启后它们的复制关系就不存在了,无法保证持久复制,所以需要在配置文件里通过参数永久设置主从复制。方式是在从库的配置文件里添加下面参数:

    slaveof 10.19.62.2 6999 #复制参数,指定主库的IP和端口号

    slave-read-only yes #设置从库为只读

    masterauth redis123 #如果主库设置了requirepass,那么从库连上主库需要有主库的密码才行,如果不设置改参数,那么主从关系可能可以建立,但是主库有数据更新时从库上不会重现(可以试一下)

  添加后重启从库,进入从库后执行info replication命令,可以发现此时复制关系仍然存在,这是因为配置文件中的参数作用。如图所示:

 

 

 

搭建sentinel服务

  sentinel中文即哨兵的意思,也就是一个“监视器”。它是通过给定的配置文件来发现主服务器,再通过向主服务器发送info信息来发现该主服务器的从服务器。Sentinel实际上就是一个运行在 Sentienl 模式下的 Redis 服务器。

  ·我们先在从服务器上搭建一个sentinel实例,来测试一下效果。首先建立sentinel实例目录:

    [wwwad@test_3 sentinel]$ sudo mkdir /data/redis/sentinel/

  ·将sentinel的配置文件拷贝到/etc/redis/下

    [wwwad@test_3 redis-3.0.7]$ cp sentinel.conf /etc/redis/sentinel_16999.conf

  ·配置一下下面的关键性的参数,其余的参数默认值即可:

    port 16999

    #指定sentinel的端口号为16999(默认为26379,这里不采用默认的)

    dir “/data/redis/sentinel”

    #指定sentinel的安装目录

    logfile “/data/redis/sentinel/sentinel_16999.log”

    #指定sentinel的日志文件存放位置

    daemonize yes

    #指定是否用守护线程的方式启动sentinel。yes代表启用守护线程,这时sentinel会在后台运行,不占用前端界面;no表不启用守护线程,这时会占用前端界面

    sentinel monitor mymaster 10.19.62.2 6999 1

    #告诉sentinel主库的位置在10.19.62.2:6999,并将该主库命名为mymaster,1表示在sentinel集群中,有多少个sentinel认为master不可用了,才能真正认定master不可用。

    sentinel auth-pass mymaster redis123

    #主库设置requirepass,这里需要指定主库的密码

  ·启动sentinel

  通过命令redis-sentinel并指定配置文件的方式启动sentinel:

    [wwwad@test_3 redis-3.0.7]$ sudo redis-sentinel /etc/redis/sentinel_16999.conf

  启动后,查看一下sentinel日志的输出信息,如上图中的倒数第二行表示sentinel找到了主库并加入了监控,倒数第一行表示找到slave并加入到slave列表。这时查看sentinel的配置文件,会发现多了这样的一行:

    sentinel known-slave mymaster 10.19.110.150 6999

  这表示sentinel将从库信息写到配置文件里保存了。

  如果日志的输出信息中没有上面的倒数第一行的信息,表示sentinel没有找到主库所对应的从库,sentinel的启动是不成功的,当主库宕机后sentinel无法实现故障转移。这时候需要进行排错,首先看日志文件的输出信息,然后可能的原因如下:

    redis-sentinel命令用得对不对;

    sentinel的配置文件配置是否正确;

    主从库的配置文件以及主从关系是否真正建立。

 

测试redis的主从故障转移

1、kill掉10.19.62.2:6999主库后的情形

  在主库上kill掉主库进程,如图:

 

  在从库上查看从库的状态:

 

  查看sentinel的故障转移过程的输出信息,如下:

13747:X 01 Aug 18:05:07.173 # +sdown master mymaster 10.19.62.2 6999

13747:X 01 Aug 18:05:07.173 # +odown master mymaster 10.19.62.2 6999 #quorum 1/1

13747:X 01 Aug 18:05:07.173 # +new-epoch 25

13747:X 01 Aug 18:05:07.173 # +try-failover master mymaster 10.19.62.2 6999

13747:X 01 Aug 18:05:07.174 # +vote-for-leader aefc57c5a4d0a78bb985d6ab4252a9dfdcd5b099 25

13747:X 01 Aug 18:05:07.174 # +elected-leader master mymaster 10.19.62.2 6999

13747:X 01 Aug 18:05:07.174 # +failover-state-select-slave master mymaster 10.19.62.2 6999

13747:X 01 Aug 18:05:07.251 # +selected-slave slave 10.19.110.150:6999 10.19.110.150 6999 @ mymaster 10.19.62.2 6999

13747:X 01 Aug 18:05:07.251 * +failover-state-send-slaveof-noone slave 10.19.110.150:6999 10.19.110.150 6999 @ mymaster 10.19.62.2 6999

13747:X 01 Aug 18:05:07.322 * +failover-state-wait-promotion slave 10.19.110.150:6999 10.19.110.150 6999 @ mymaster 10.19.62.2 6999

13747:X 01 Aug 18:05:08.214 # +promoted-slave slave 10.19.110.150:6999 10.19.110.150 6999 @ mymaster 10.19.62.2 6999

13747:X 01 Aug 18:05:08.214 # +failover-state-reconf-slaves master mymaster 10.19.62.2 6999

13747:X 01 Aug 18:05:08.284 # +failover-end master mymaster 10.19.62.2 6999

13747:X 01 Aug 18:05:08.284 # +switch-master mymaster 10.19.62.2 6999 10.19.110.150 6999

13747:X 01 Aug 18:05:08.284 * +slave slave 10.19.62.2:6999 10.19.62.2 6999 @ mymaster 10.19.110.150 6999

13747:X 01 Aug 18:05:23.343 # +sdown slave 10.19.62.2:6999 10.19.62.2 6999 @ mymaster 10.19.110.150 6999

  在这个转移过程中,10.19.110.150:6999的配置文件和sentinel配置文件都有参数改变:10.19.110.150:6999配置文件的slaveof参数被删除;sentinel配置文件sentinel monitor参数指向了新的主库:sentinel monitor mymaster 10.19.110.150 6999 1;sentinel known-slave参数指向了刚才宕掉的10.19.62.2:6999库:sentinel known-slave mymaster 10.19.62.2 6999

 

2、重新启动10.19.62.2:6999实例后的情形

  重新启动10.19.62.2:6999,重启后进入数据库中查看复制状态,如图:

 

  这里10.19.62.2:6999启动后即成为10.19.110.150:6999的从库,要知道在启动10.19.62.2:6999时,其配置文件中是没有slaveof参数,但是这里还是建立复制关系。这是因为在之前的故障转移时,sentinel把10.19.62.2:6999作为10.19.110.150:6999的slave存到了配置文件中,如下图:

 

  sentinel通过这条配置信息为二者建立了主从关系。再查看10.19.62.2:6999实例的配置文件,会发现多了”slaveof 10.19.110.150 6999″信息,如图:

 

  这时新的主从关系确立了:10.19.62.2:6999变成了从,10.19.110.150:6999变成了主。下面再模拟主库宕机,看sentinel还能不能再切过来。

3、kill掉10.19.110.150:6999后的情形

  查看10.19.110.150:6999实例的进程id后并杀死,这时在10.19.62.2:6999上查看复制状态,可以看出和预想的一样,10.19.62.2:6999成为了主库。

 

  这时再查看下10.19.62.2:6999的配置文件信息,看看还有没有”slaveof 10.19.110.150 6999″信息,如下图:

 

  很明显,10.19.62.2:6999配置文件中的这条参数配置已被删除。另外再查看sentinel的配置文件,相应地主从库配置也改变了:

 

  同样地,当启动10.19.110.150:6999实例后,将自动与10.19.62.2:6999建立主从关系,并且10.19.110.150:6999的配置文件里添加了slaveof参数:

 

4、测试sentinel的sentinel notification-script和sentinel client-reconfig-script参数

  网上有文章说notification-script参数指定的脚本不会执行,而client-reconfig-script参数指定的脚本会执行,下面来验证一下。

测试client-reconfig-script参数:

  先编辑一个简单的脚本,脚本位于/var/redis/目录下,并赋予脚本可执行权限:chmod 755 /var/redis/reconfig.sh,脚本内容如下:

 

  在sentinel的配置文件中添加如下一行参数:

    sentinel client-reconfig-script mymaster /var/redis/reconfig.sh

  重新启动sentinel:

    [wwwad@test_3 sentinel]$ redis-cli -p 16999 shutdown

    [wwwad@test_3 sentinel]$ sudo redis-sentinel /etc/redis/sentinel_16999.conf

  此时在/home/wwwad/目录下是没有test_1文件的:

 

  现在kill掉redis主库,这时会进行主库切换,sentinel根据配置文件里的client-reconfig-script参数也会去执行reconfig.sh脚本,是否执行过该脚本可以看/home/wwwad/下有没有test_1文件:

 

  可以看出,该参数指定脚本是会执行的。

测试sentinel notification-script参数:

  在sentinel配置文件里注释掉sentinel client-reconfig-script参数,添加sentinel notification-script参数:

 

  再重启sentinel,并将/home/wwwad/目录下的test_1文件删除:

 

  此时再模拟一次主库故障,即kill掉主库,过一会在/home/wwwad目录下发现test_1文件同样被创建:

 

  可以看出sentinel notification-script参数指定的脚本同样会执行。所以这两个参数基本上都是有效的。

 

  上面的搭建中,只在10.19.110.150服务器上搭建了一个sentinel,但是一个sentinel容易出现单点问题,所以我们需要配置sentinel集群,在10.19.62.2和10.19.110.150两台服务器上各搭建两个sentinel实例,即redis架构由上图向下图转换:

 

 

 

  先创建sentinel的dir目录,然后将redis安装目录下的sentinel.conf文件复制到/etc/redis/目录下:

    [wwwad@P2P-test1 redis]$ sudo mkdir sentinel_15999

    [wwwad@P2P-test1 redis-3.0.7]$ cp sentinel.conf /etc/redis/sentinel_15999.conf

  修改下sentinel的配置文件,进行如下的基本配置:

    port 15999

    dir “/data/redis/sentinel_15999”

    logfile “/data/redis/sentinel_15999/sentinel_1599.log”

    daemonize yes

    sentinel monitor mymaster 10.19.62.2 6999 3

    sentinel down-after-milliseconds mymaster 15000

    sentinel auth-pass mymaster redis123

    sentinel config-epoch mymaster 38

    sentinel leader-epoch mymaster 0

    sentinel current-epoch 38

  然后开始启动各个sentinel实例,启动后再看各个sentinel的配置文件,会增加如下几行配置信息(以10.19.62.2:15999为例):

 

  上图表示每个sentinel实例都识别到了10.19.110.150:6999从实例以及另外三个sentinel实例的信息,此时构成了sentinel实例集群。

  此时redis主从、sentinel监控集群都部署完毕,再模拟故障转移场景。

sentinel集群下的主库故障转移

  在主库10.19.62.2:6999上kill掉主库实例并同时记录kill掉的时间:

 

  查看10.19.62.2:16999 sentinel的日志文件,如下:

15168:X 03 Aug 11:42:42.164 # +sdown master mymaster 10.19.62.2 6999

#主观检测到主库不可用

15168:X 03 Aug 11:42:42.222 # +odown master mymaster 10.19.62.2 6999 #quorum 4/3

#投票完成,客观认为主库是不可用的

#这里quorum 4/3感觉有些问题,四个sentinel都将quorum配置为3,但是这里居然是4/3,应该是3/3才合理,但是故障转移过程也实现了。。。

15168:X 03 Aug 11:42:42.222 # +new-epoch 43

15168:X 03 Aug 11:42:42.222 # +try-failover master mymaster 10.19.62.2 6999

#开始准备转移主库

15168:X 03 Aug 11:42:42.224 # +vote-for-leader 9d853e5036cf96fbfea10c1a717296ee353f0de3 43

15168:X 03 Aug 11:42:42.226 # 10.19.62.2:15999 voted for 9d853e5036cf96fbfea10c1a717296ee353f0de3 43

15168:X 03 Aug 11:42:42.236 # 10.19.110.150:15999 voted for 9d853e5036cf96fbfea10c1a717296ee353f0de3 43

15168:X 03 Aug 11:42:42.236 # 10.19.110.150:16999 voted for 9d853e5036cf96fbfea10c1a717296ee353f0de3 43

#以上都是在选举sentinel leader

15168:X 03 Aug 11:42:42.300 # +elected-leader master mymaster 10.19.62.2 6999

15168:X 03 Aug 11:42:42.300 # +failover-state-select-slave master mymaster 10.19.62.2 6999

#准备选择一个slave来充当新主

15168:X 03 Aug 11:42:42.377 # +selected-slave slave 10.19.110.150:6999 10.19.110.150 6999 @ mymaster 10.19.62.2 6999

#选择10.19.110.150:6999为新主

15168:X 03 Aug 11:42:42.377 * +failover-state-send-slaveof-noone slave 10.19.110.150:6999 10.19.110.150 6999 @ mymaster 10.19.62.2 6999

#改变10.19.110.150:6999的身份,即去除掉其配置文件里slaveof参数

15168:X 03 Aug 11:42:42.439 * +failover-state-wait-promotion slave 10.19.110.150:6999 10.19.110.150 6999 @ mymaster 10.19.62.2 6999

15168:X 03 Aug 11:42:43.287 # +promoted-slave slave 10.19.110.150:6999 10.19.110.150 6999 @ mymaster 10.19.62.2 6999

#提升10.19.110.150:6999为主库

15168:X 03 Aug 11:42:43.287 # +failover-state-reconf-slaves master mymaster 10.19.62.2 6999

15168:X 03 Aug 11:42:43.368 # +failover-end master mymaster 10.19.62.2 6999

#表示故障转移成功

15168:X 03 Aug 11:42:43.369 # +switch-master mymaster 10.19.62.2 6999 10.19.110.150 6999

#master的地址发生变化

15168:X 03 Aug 11:42:43.369 * +slave slave 10.19.62.2:6999 10.19.62.2 6999 @ mymaster 10.19.110.150 6999

15168:X 03 Aug 11:42:58.420 # +sdown slave 10.19.62.2:6999 10.19.62.2 6999 @ mymaster 10.19.110.150 6999

#以上是添加其他slave到新主下,但10.19.62.2:6999处于不可用状态

 

查看日志,发现sentinel是在11:42:42秒开始进行故障转移,到11:42:58秒结束,而故障是发生在11:42:27秒。