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秒。