keepalived+redis 高可用redis主从解决方案-阿里云开发者社区

开发者社区> 开发与运维> 正文

keepalived+redis 高可用redis主从解决方案

简介:

环境介绍:

Master: 192.168.0.100

Slave: 192.168.0.101

Virtural IP Address (VIP): 192.168.0.200


设计思路:

当 Master 与 Slave 均运作正常时, Master负责服务,Slave负责Standby;

当 Master 挂掉,Slave 正常时, Slave接管服务,同时关闭主从复制功能;

当 Master 恢复正常,则从Slave同步数据,同步数据之后关闭主从复制功能,恢复Master身份,于此同时Slave等待Master同步数据完成之后,恢复Slave身份。

然后依次循环。


需要注意的是,这样做需要在Master与Slave上都开启本地化策略,否则在互相自动切换的过程中,未开启本地化的一方会将另一方的数据清空,造成数据完全丢失。


下面,是具体的实施步骤:


Keepalived是一个免费开源的,用C编写的类似于layer3, 4 & 7交换机制软件,具备我们平时说的第3层、第4层和第7层交换机的功能。主要提供loadbalancing(负载均衡)和 high-availability(高可用)功能,负载均衡实现需要依赖Linux的虚拟服务内核模块(ipvs),而高可用是通过VRRP协议实现多台机器之间的故障转移服务。

Keepalived体系结构


上图是Keepalived的功能体系结构,大致分两层:用户空间(user space)和内核空间(kernel space)。 

内核空间:主要包括IPVS(IP虚拟服务器,用于实现网络服务的负载均衡)和NETLINK(提供高级路由及其他相关的网络功能)两个部份。

 

用户空间:

WatchDog:负载监控checkers和VRRP进程的状况

VRRP Stack:负载负载均衡器之间的失败切换FailOver,如果只用一个负载均稀器,则VRRP不是必须的。

Checkers:负责真实服务器的健康检查healthchecking,是keepalived最主要的功能。换言之,可以没有VRRP Stack,但健康检查healthchecking是一定要有的。


IPVS wrapper:用户发送设定的规则到内核ipvs代码


Netlink Reflector:用来设定vrrp的vip地址等。


Keepalived的所有功能是配置keepalived.conf文件来实现的。


二、安装与配置

从官网下载keepalived的最新版本,本文以当前最新版本1.2.24为例。

2.1 安装


shell> cd /usr/local/src

shell> wget 

shell> tar -zxvf keepalived-1.2.24.tar.gz

shell> cd keepalived-1.2.24

shell> ./configure --prefix=/usr/local/keepalived

shell> make && make install



keepalived执行./configure --prefix=/usr/local/keepalived时报错:configure: error: Popt libraries is required

出现此错误的原因:

未安装popt的开发包


解决方法:

yum install popt-devel

安装好popt的开发包。


重新./configure 即可。


2.2 配置

安装完成后,进入安装目录的etc目录下,将keepalived相应的配置文件拷贝到系统相应的目录当中。

keepalived启动时会从/etc/keepalived目录下查找keepalived.conf配置文件,如果没有找到则使用默

认的配置。/etc/keepalived目录安装时默认是没有安装的,需要手动创建。配置文件目录结构如下所示:


shell> tree -l /usr/local/keepalived/etc

-- keepalived

|   |-- keepalived.conf

|   `-- samples

|       |-- keepalived.conf.status_code

|       |-- keepalived.conf.track_interface

|       |-- keepalived.conf.vrrp

|       |-- 。。。

|-- rc.d

|   `-- init.d

|       `-- keepalived

`-- sysconfig

    `-- keepalived


分别对应系统目录(忽略samples目录):


/etc/keepalived/keepalived.conf


/etc/rc.d/init.d/keepalived


/etc/sysconfig/keepalived


将配置文件拷贝到系统对应的目录下:


shell> mkdir /etc/keepalived

shell> cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf

shell> cp /usr/local/keepalived/sbin/keepalived /etc/rc.d/init.d/keepalived

shell> cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/keepalived


设置keepalived服务开机启动:


shell> chkconfig keepalived on

shell> service keepalived start   #启动服务


shell> service keepalived stop    #停止服务


shell> service keepalived restart #重启服务


另外需要注意的一点是,keepalived启动时不会检查配置文件的语法是否正确,所以我们在编写配置文件时要特别小心,别写错了,否则会出现一些意想不到的现象。


使用service keepalived start命令启动服务时,默认会将/etc/sysconfig/keepalived文件中KEEPALIVED_OPTIONS参数作为keepalived服务启动时的参数


并从/etc/keepalived/目录下加载keepalived.conf配置文件,或用-f参数指定配置文件的位置


# Options for keepalived. See `keepalived --help' output and keepalived(8) and

# keepalived.conf(5) man pages for a list of all options. Here are the most

# common ones :

#

# --vrrp               -P    Only run with VRRP subsystem.

# --check              -C    Only run with Health-checker subsystem.

# --dont-release-vrrp  -V    Dont remove VRRP VIPs & VROUTEs on daemon stop.

# --dont-release-ipvs  -I    Dont remove IPVS topology on daemon stop.

# --dump-conf          -d    Dump the configuration data.

# --log-detail         -D    Detailed log messages.日志默认输出在/var/log/message文件中

# --log-facility       -S    0-7 Set local syslog facility (default=LOG_DAEMON)

#

KEEPALIVED_OPTIONS="-D"


运行keepalived --help可以查看启动时的可选参数,这些可选参数都可以配置


在/etc/sysconfig/keepalived文件中的KEEPALIVED_OPTIONS选项中,作为服务启动时的参数。


keepalived正常运行后,会启动3个进程,其中一个是父进程,负责监控其子进程。


一个是vrrp子进程,另外一个是checkers子进程。


shell> ps -ef | grep keepalived

root       831     1  0 11:22 ?        00:00:00 keepalived -D

root       840   831  0 11:22 ?        00:00:00 keepalived -D

root       841   831  0 11:22 ?        00:00:00 keepalived -D


到此keepalived就安装完成了。


三、keepalived.conf配置文件说明

keepalived服务安装完成之后,后面的主要工作就是在keepalived.conf文件中配置HA和负载均衡。一个功能比较完整的常用的keepalived配置文件,主要包含三块:


全局定义块、


VRRP实例定义块和


虚拟服务器定义块。


全局定义块是必须的,如果keepalived只用来做ha,虚拟服务器是可选的。


下面是一个功能比较完整的配置文件模板:


#全局定义块

global_defs {    

        # 邮件通知配置

    notification_email {

        email1

        email2

    }

    notification_email_from email

    smtp_server host

    smtp_connect_timeout num

 

    lvs_id string

    router_id string    ## 标识本节点的字条串,通常为hostname

}

 

#VRRP 实例定义块

vrrp_sync_group string { 

    group {        

         string

        string

    }

}

 

vrrp_instance string {

    state MASTER|BACKUP

    virtual_router_id num

    interface string

    mcast_src_ip @IP 

    priority num

    advert_int num

    nopreempt

    smtp_alert

    lvs_sync_daemon_interface string 

    authentication {

        auth_type PASS|AH

        auth_pass string

    }

 

    virtual_ipaddress {  # Block limited to 20 IP addresses @IP

        @IP

        @IP

    }

}

 

#虚拟服务器定义块

virtual_server (@IP PORT)|(fwmark num) { 

    delay_loop num

    lb_algo rr|wrr|lc|wlc|sh|dh|lblc 

    lb_kind NAT|DR|TUN

    persistence_timeout num 

    protocol TCP|UDP

    real_server @IP PORT { 

        weight num

        notify_down /path/script.sh

        TCP_CHECK { 

            connect_port num 

            connect_timeout num

        }

    }

 

    real_server @IP PORT {

        weight num

        MISC_CHECK {

            misc_path /path_to_script/script.sh(or misc_path “/path_to_script/script.sh <arg_list>”)

        }

    }

 

    real_server @IP PORT {

        weight num

        HTTP_GET|SSL_GET {

            url { 

                # You can add multiple url block path alphanum

                digest alphanum

            }

            connect_port num

            connect_timeout num 

            nb_get_retry num 

            delay_before_retry num

        }

    }

}


全局定义块

1、email通知(notification_email、smtp_server、smtp_connect_timeout):用于服务有故障时发送邮件报警,可选项,不建议用。需要系统开启sendmail服务,建议用第三独立监控服务,如用nagios全面监控代替。

 

2、lvs_id:lvs负载均衡器标识,在一个网络内,它的值应该是唯一的。

 

3、router_id:用户标识本节点的名称,通常为hostname 


4、花括号{}:用来分隔定义块,必须成对出现。如果写漏了,keepalived运行时不会得到预期的结果。由于定义块存在嵌套关系,因此很容易遗漏结尾处的花括号,这点需要特别注意。


VRRP实例定义块

vrrp_sync_group:同步vrrp级,用于确定失败切换(FailOver)包含的路由实例个数。即在有2个负载均衡器的场景,一旦某个负载均衡器失效,需要自动切换到另外一个负载均衡器的实例是哪


group:至少要包含一个vrrp实例,vrrp实例名称必须和vrrp_instance定义的一致


vrrp_instance:vrrp实例名 


1> state:实例状态,只有MASTER 和 BACKUP两种状态,并且需要全部大写。抢占模式下,其中MASTER为工作状态,BACKUP为备用状态。当MASTER所在的服务器失效时,BACKUP所在的服务会自动把它的状态由BACKUP切换到MASTER状态。当失效的MASTER所在的服务恢复时,BACKUP从MASTER恢复到BACKUP状态。 


2> interface:对外提供服务的网卡接口,即VIP绑定的网卡接口。如:eth0,eth1。当前主流的服务器都有2个或2个以上的接口(分别对应外网和内网),在选择网卡接口时,一定要核实清楚。

 

3> mcast_src_ip:本机IP地址 


4> virtual_router_id:虚拟路由的ID号,每个节点设置必须一样,可选择IP最后一段使用,相同的 VRID 为一个组,他将决定多播的 MAC 地址。

 

5> priority:节点优先级,取值范围0~254,MASTER要比BACKUP高 


6> advert_int:MASTER与BACKUP节点间同步检查的时间间隔,单位为秒 


7> lvs_sync_daemon_inteface:负载均衡器之间的监控接口,类似于 HA HeartBeat 的心跳线。但它的机制优于 Heartbeat,因为它没有“裂脑”这个问题,它是以优先级这个机制来规避这个麻烦的。在 DR 模式中,lvs_sync_daemon_inteface与服务接口interface使用同一个网络接口 


8> authentication:验证类型和验证密码。类型主要有 PASS、AH 两种,通常使用PASS类型,据说AH使

用时有问题。验证密码为明文,同一vrrp 实例MASTER与BACKUP使用相同的密码才能正常通信

 

9> smtp_alert:有故障时是否激活邮件通知 


10> nopreempt:禁止抢占服务。默认情况,当MASTER服务挂掉之后,BACKUP自动升级为MASTER并接替它的任务,当MASTER服务恢复后,升级为MASTER的BACKUP服务又自动降为BACKUP,把工作权交给原MASTER。当配置了nopreempt,MASTER从挂掉到恢复,不再将服务抢占过来。 


11> virtual_ipaddress:虚拟IP地址池,可以有多个IP,每个IP占一行,不需要指定子网掩码。注意:这个IP必须与我们的设定的vip保持一致。


虚拟服务器virtual_server定义块


virtual_server:定义一个虚拟服务器,这个ip是virtual_ipaddress中定义的其中一个,后面一个空格,然后加上虚拟服务的端口号。 


1> delay_loop:健康检查时间间隔,单位:秒 

2> lb_algo:负载均衡调度算法,互联网应用常用方式为wlc或rr 

3> lb_kind:负载均衡转发规则。包括DR、NAT、TUN 3种,一般使用路由(DR)转发规则。 

4> persistence_timeout:http服务会话保持时间,单位:秒 

5> protocol:转发协议,分为TCP和UDP两种

real_server:真实服务器IP和端口,可以定义多个 

1> weight:负载权重,值越大,转发的优先级越高 

2> notify_down:服务停止后执行的脚本 

3> TCP_CHECK:服务有效性检测 

    * connect_port:服务连接端口 

    * connect_timeout:服务连接超时时长,单位:秒 

    * nb_get_retry:服务连接失败重试次数 

    * delay_before_retry:重试连接间隔,单位:秒



在Master和Slave上安装Keepalived



默认安装完成keepalived有默认的配置文件,因此我们重写覆盖它:


首先,在Master上创建如下配置文件:


$ vim /etc/keepalived/keepalived.conf


! Configuration File for keepalived

global_defs {

   router_id redis100  #用户标识本节点的名称,通常为hostname 

}

vrrp_script chk_redis 

     script "/etc/keepalived/scripts/redis_check.sh 127.0.0.1 6379" 

     interval 2 

     timeout 2

     fall 3

}

vrrp_instance redis {

     state MASTER        # master set to SLAVE also

     interface eth0      #对外提供服务的网卡接口,即VIP绑定的网卡接口

     virtual_router_id 50  #虚拟路由的ID号,每个节点设置必须一样,可选择IP最后一段使用,相同的 VRID 为一个组,他将决定多播的 MAC 地址。 

     priority  150      #节点优先级,取值范围0~254,MASTER要比BACKUP高    

     nopreempt          #禁止抢占服务  no seize,must add

     advert_int 1        #ASTER与BACKUP节点间同步检查的时间间隔,单位为秒

authentication {        #all node must same

         auth_type PASS

         auth_pass 1111

    }

  

    virtual_ipaddress {  

192.168.0.200/24

    }

    track_script { 

         chk_redis 

    } 

     notify_master "/etc/keepalived/scripts/redis_master.sh 127.0.0.1 192.168.0.101 6379"

     notify_backup "/etc/keepalived/scripts/redis_backup.sh 127.0.0.1 192.168.0.101 6379"

     notify_fault /etc/keepalived/scripts/redis_fault.sh 

     notify_stop /etc/keepalived/scripts/redis_stop.sh 

}



然后,在Slave上创建如下配置文件:


! Configuration File for keepalived

global_defs {

   router_id redis101

}

vrrp_script chk_redis 

     script "/etc/keepalived/scripts/redis_check.sh 127.0.0.1 6379" 

     interval 2

     timeout 2

     fall 3

}

vrrp_instance redis {

    state BACKUP   

    interface eth0   

    virtual_router_id 50  

    priority  100       

    advert_int 1

authentication {   #all node must same

        auth_type PASS

        auth_pass 1111

    }

  

    virtual_ipaddress { 

    192.168.0.200/24

    }

    track_script { 

         chk_redis 

    } 

    notify_master "/etc/keepalived/scripts/redis_master.sh 127.0.0.1 192.168.0.100 6379"

    notify_backup "/etc/keepalived/scripts/redis_backup.sh 127.0.0.1 192.168.0.100 6379"

    notify_fault /etc/keepalived/scripts/redis_fault.sh 

    notify_stop /etc/keepalived/scripts/redis_stop.sh 

}



在Master和Slave上创建监控Redis的脚本


$ mkdir /etc/keepalived/scripts

$ vim /etc/keepalived/scripts/redis_check.sh


#!/bin/bash 

ALIVE=`/usr/redis/redis-cli -h $1 -p $2 PING` 

LOGFILE="/var/log/keepalived-redis-check.log" 

echo "[CHECK]" >> $LOGFILE

date >> $LOGFILE

if [ $ALIVE == "PONG" ]; then :

   echo "Success: redis-cli -h $1 -p $2 PING $ALIVE" >> $LOGFILE 2>&1

    exit 0 

else 

    echo "Failed:redis-cli -h $1 -p $2 PING $ALIVE " >> $LOGFILE 2>&1

    exit 1 

fi

编写以下负责运作的关键脚本:


notify_master /etc/keepalived/scripts/redis_master.sh


notify_backup /etc/keepalived/scripts/redis_backup.sh


notify_fault /etc/keepalived/scripts/redis_fault.sh


notify_stop /etc/keepalived/scripts/redis_stop.sh


因为Keepalived在转换状态时会依照状态来呼叫:

当进入Master状态时会呼叫notify_master

当进入Backup状态时会呼叫notify_backup

当发现异常情况时进入Fault状态呼叫notify_fault

当Keepalived程序终止时则呼叫notify_stop


首先,在Redis Master上创建notity_master与notify_backup脚本:


$ vim /etc/keepalived/scripts/redis_master.sh


#!/bin/bash 

REDISCLI="/usr/redis/redis-cli -h $1 -p $3" 

LOGFILE="/var/log/keepalived-redis-state.log" 

echo "[master]" >> $LOGFILE 

date >> $LOGFILE 

echo "Being master...." >> $LOGFILE 2>&1  

echo "Run MASTER cmd ..." >> $LOGFILE 2>&1

$REDISCLI SLAVEOF $2 $3 >> $LOGFILE  

sleep 10 #delay 10 s wait data async cancel sync

echo "Run SLAVEOF NO ONE cmd ..." >> $LOGFILE

$REDISCLI SLAVEOF NO ONE >> $LOGFILE 2>&1



$ sudo vim /etc/keepalived/scripts/redis_backup.sh


#!/bin/bash 

REDISCLI="/usr/redis/redis-cli" 

LOGFILE="/var/log/keepalived-redis-state.log" 

echo "[backup]" >> $LOGFILE 

date >> $LOGFILE 

echo "Run SLAVEOF cmd ..." >> $LOGFILE 

$REDISCLI SLAVEOF $2 $3 >> $LOGFILE 2>&1 

# echo "Being slave...." >> $LOGFILE 2>&1 

sleep 15 #delay 15 s wait data sync exchange role


接着,在Redis Slave上创建notity_master与notify_backup脚本:


$ vim /etc/keepalived/scripts/redis_master.sh



#!/bin/bash 

REDISCLI="/usr/redis/redis-cli -h $1 -p $3" 

LOGFILE="/var/log/keepalived-redis-state.log" 

echo "[master]" >> $LOGFILE 

date >> $LOGFILE 

echo "Being master...." >> $LOGFILE 2>&1 

echo "Run SLAVEOF cmd ... " >> $LOGFILE 

$REDISCLI SLAVEOF $2 $3 >> $LOGFILE  2>&1

#echo "SLAVEOF $2 cmd can't excute ... " >> $LOGFILE 

sleep 10 ##delay 15 s wait data sync exchange role

echo "Run SLAVEOF NO ONE cmd ..." >> $LOGFILE

$REDISCLI SLAVEOF NO ONE >> $LOGFILE 2>&1


$ vim /etc/keepalived/scripts/redis_backup.sh


#!/bin/bash 

REDISCLI="/usr/redis/redis-cli" 

LOGFILE="/var/log/keepalived-redis-state.log" 

echo "[BACKUP]" >> $LOGFILE 

date >> $LOGFILE 

echo "Being slave...." >> $LOGFILE 2>&1 

echo "Run SLAVEOF cmd ..." >> $LOGFILE 2>&1

$REDISCLI SLAVEOF $2 $3 >> $LOGFILE  

sleep 100 #delay 10 s wait data async cancel sync 

exit(0)

然后在Master与Slave创建如下相同的脚本:


$ vim /etc/keepalived/scripts/redis_fault.sh


#!/bin/bash 

LOGFILE=/var/log/keepalived-redis-state.log 

echo "[fault]" >> $LOGFILE

date >> $LOGFILE

$ sudo vim /etc/keepalived/scripts/redis_stop.sh


#!/bin/bash 

LOGFILE=/var/log/keepalived-redis-state.log 

echo "[stop]" >> $LOGFILE 

date >> $LOGFILE

给脚本都加上可执行权限:

(这点很重要,最开始由于这不没做,运行后一直报错 "VRRP_Instance(Redis) Now in FAULT state")


$ sudo chmod +x /etc/keepalived/scripts/*.sh


脚本创建完成以后,我们开始按照如下流程进行测试:

1.启动Master上的Redis

$ /etc/init.d/redis start


2.启动Slave上的Redis

$ /etc/init.d/redis start


3.启动Master上的Keepalived

$ /etc/init.d/keepalived start


4.启动Slave上的Keepalived

$ /etc/init.d/keepalived start



5.尝试通过VIP连接Redis:

$ redis-cli -h 10.6.1.200 INFO


连接成功,Slave也连接上来了。

role:master

slave0:10.6.1.144,6379,online


6.尝试插入一些数据:

$ redis-cli -h 10.6.1.200 SET Hello Redis

OK


从VIP读取数据

$ redis-cli -h 10.6.1.200 GET Hello

"Redis"


从Master读取数据

$ redis-cli -h 10.6.1.143 GET Hello

"Redis"


从Slave读取数据

$ redis-cli -h 10.6.1.144 GET Hello

"Redis"



下面,模拟故障产生:

将Master上的Redis停了

$ service redis_6379 stop


查看Master上的Keepalived日志

$ tailf /var/log/keepalived-redis-state.log

[fault]

Thu Sep 27 08:29:01 CST 2012


同时Slave上的日志显示:

$ tailf /var/log/keepalived-redis-state.log

[master]

Fri Sep 28 14:14:09 CST 2012

Being master....

Run SLAVEOF cmd ...

OK

Run SLAVEOF NO ONE cmd ...

OK


然后我们可以发现,Slave已经接管服务,并且担任Master的角色了。

$ redis-cli -h 192.168.0.200 INFO


role:master


然后我们恢复Master的Redis进程

$ service redis_6379 start


查看Master上的Keepalived日志

$ tailf /var/log/keepalived-redis-state.log

[master]

Thu Sep 27 08:31:33 CST 2012

Being master....

Run SLAVEOF cmd ...

OK

Run SLAVEOF NO ONE cmd ...

OK


同时Slave上的日志显示:

$ tailf /var/log/keepalived-redis-state.log

[backup]

Fri Sep 28 14:16:37 CST 2012

Being slave....

Run SLAVEOF cmd ...

OK


可以发现目前的Master已经再次恢复了Master的角色,故障切换以及自动恢复都成功了。



注意事项:主从的redis都要开启本地备份


附:

Redis Sentinel的主从切换方案

Redis 2.8版开始正式提供名为Sentinel的主从切换方案,Sentinel用于管理多个Redis服务器实例,主要负责三个方面的任务:


    1. 监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。

    2. 提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。

    3. 自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。


Redis Sentinel 是一个分布式系统, 你可以在一个架构中运行多个 Sentinel 进程(progress), 这些进程使用流言协议(gossip protocols)来接收关于主服务器是否下线的信息, 并使用投票协议(agreement protocols)来决定是否执行自动故障迁移, 以及选择哪个从服务器作为新的主服务器。


启动Sentinel

使用--sentinel参数启动,并必须指定一个对应的配置文件,系统会使用配置文件来保存 Sentinel 的当前状态, 并在 Sentinel 重启时通过载入配置文件来进行状态还原。


    redis-server /path/to/sentinel.conf --sentinel


使用TCP端口26379,可以使用redis-cli或其他任何客户端与其通讯。


如果启动 Sentinel 时没有指定相应的配置文件, 或者指定的配置文件不可写(not writable), 那么 Sentinel 会拒绝启动。


配置Sentinel

以下是一段配置文件的示例:


sentinel monitor mymaster 127.0.0.1 6379 2

sentinel down-after-milliseconds mymaster 60000

sentinel failover-timeout mymaster 180000

sentinel parallel-syncs mymaster 1


sentinel monitor resque 192.168.1.3 6380 4

sentinel down-after-milliseconds resque 10000

sentinel failover-timeout resque 180000

sentinel parallel-syncs resque 5


    第一行配置指示 Sentinel 去监视一个名为 mymaster 的主服务器, 这个主服务器的 IP 地址为 127.0.0.1 , 端口号为 6379 , 而将这个主服务器判断为失效至少需要 2 个 Sentinel 同意 (只要同意 Sentinel 的数量不达标,自动故障迁移就不会执行)。


    不过需要注意的是,无论你设置要多少个 Sentinel 同意才能判断一个服务器失效,一个 Sentinel 都需要获得系统中多数(majority) Sentinel 的支持,才能发起一次自动故障迁移,并预留一个给定的配置纪元 (Configuration Epoch ,一个配置纪元就是一个新主服务器配置的版本号)。也就是说,如果只有少数(minority)Sentinel 进程正常运作的情况下,是不能执行自动故障迁移的。


    down-after-milliseconds 选项指定了 Sentinel 认为服务器已经断线所需的毫秒数(判定为主观下线SDOWN)。

    parallel-syncs 选项指定了在执行故障转移时, 最多可以有多少个从服务器同时对新的主服务器进行同步, 这个数字越小, 完成故障转移所需的时间就越长,但越大就意味着越多的从服务器因为复制而不可用。可以通过将这个值设为 1 来保证每次只有一个从服务器处于不能处理命令请求的状态。


主观下线和客观下线

    1. 主观下线(Subjectively Down, 简称 SDOWN)指的是单个 Sentinel 实例对服务器做出的下线判断。

    2. 客观下线(Objectively Down, 简称 ODOWN)指的是多个 Sentinel 实例在对同一个服务器做出 SDOWN 判断, 并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后, 得出的服务器下线判断。


客观下线条件只适用于主服务器: 对于任何其他类型的 Redis 实例, Sentinel 在将它们判断为下线前不需要进行协商, 所以从服务器或者其他 Sentinel 永远不会达到客观下线条件。

只要一个 Sentinel 发现某个主服务器进入了客观下线状态, 这个 Sentinel 就可能会被其他 Sentinel 推选出, 并对失效的主服务器执行自动故障迁移操作。


每个Sentinel实例都执行的定时任务

    1. 每个 Sentinel 以每秒钟一次的频率向它所知的主服务器、从服务器以及其他 Sentinel 实例发送一个 PING 命令。

    2. 如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 那么这个实例会被 Sentinel 标记为主观下线。 一个有效回复可以是: +PONG 、 -LOADING 或者 -MASTERDOWN 。

    3. 如果一个主服务器被标记为主观下线, 那么正在监视这个主服务器的所有 Sentinel 要以每秒一次的频率确认主服务器的确进入了主观下线状态。

    4. 如果一个主服务器被标记为主观下线, 并且有足够数量的 Sentinel (至少要达到配置文件指定的数量)在指定的时间范围内同意这一判断, 那么这个主服务器被标记为客观下线。

    5. 在一般情况下, 每个 Sentinel 会以每 10 秒一次的频率向它已知的所有主服务器和从服务器发送 INFO 命令。 当一个主服务器被 Sentinel 标记为客观下线时, Sentinel 向下线主服务器的所有从服务器发送 INFO 命令的频率会从 10 秒一次改为每秒一次。

    6. 当没有足够数量的 Sentinel 同意主服务器已经下线, 主服务器的客观下线状态就会被移除。 当主服务器重新向 Sentinel 的 PING 命令返回有效回复时, 主服务器的主管下线状态就会被移除。


Sentinel API

有两种方式可以与Sentinel进行通讯:指令、发布与订阅。


    Sentinel命令

       PING :返回 PONG 。

       SENTINEL masters :列出所有被监视的主服务器,以及这些主服务器的当前状态;

       SENTINEL slaves <master name> :列出给定主服务器的所有从服务器,以及这些从服务器的当前状态;

       SENTINEL get-master-addr-by-name <master name> : 返回给定名字的主服务器的 IP 地址和端口号。 如果这个主服务器正在执行故障转移操作, 或者针对这个主服务器的故障转移操作已经完成, 那么这个                     命令返回新的主服务器的 IP 地址和端口号;

       SENTINEL reset <pattern> : 重置所有名字和给定模式 pattern 相匹配的主服务器。 pattern 参数是一个 Glob 风格的模式。 重置操作清楚主服务器目前的所有状态, 包括正在执行中的故障转移, 并移除目前已经发现和关联的, 主服务器的所有从服务器和 Sentinel ;

       SENTINEL failover <master name> : 当主服务器失效时, 在不询问其他 Sentinel 意见的情况下, 强制开始一次自动故障迁移。


客户端可以通过SENTINEL get-master-addr-by-name <master name>获取当前的主服务器IP地址和端口号,以及SENTINEL slaves <master name>获取所有的Slaves信息


    发布与订阅信息

    客户端可以将 Sentinel 看作是一个只提供了订阅功能的 Redis 服务器: 你不可以使用 PUBLISH 命令向这个服务器发送信息, 但你可以用 SUBSCRIBE 命令或者 PSUBSCRIBE 命令, 通过订阅给定的频道来获取相应的事件提醒。

   一个频道能够接收和这个频道的名字相同的事件。 比如说, 名为 +sdown 的频道就可以接收所有实例进入主观下线(SDOWN)状态的事件。

   通过执行 PSUBSCRIBE * 命令可以接收所有事件信息。


        +switch-master <master name> <oldip> <oldport> <newip> <newport> :配置变更,主服务器的 IP 和地址已经改变。 这是绝大多数外部用户都关心的信息。


    可以看出,我们使用Sentinel命令和发布订阅两种机制就能很好的实现和客户端的集成整合:

    使用get-master-addr-by-name和slaves指令可以获取当前的Master和Slaves的地址和信息;而当发生故障转移时,即Master发生切换,可以通过订阅的+switch-master事件获得最新的Master信息。


    *PS:更多Sentinel的可订阅事件参见官方文档。


sentinel.conf中的notification-script

    在sentinel.conf中可以配置多个sentinel notification-script <master name> <shell script-path>, 如sentinel notification-script mymaster ./check.sh


    这个是在群集failover时会触发执行指定的脚本。脚本的执行结果若为1,即稍后重试(最大重试次数为10);若为2,则执行结束。并且脚本最大执行时间为60秒,超时会被终止执行。


    PS:目前会存在该脚本被执行多次的问题,查找资料有人解释是:

        脚本分为两个级别, SENTINEL_LEADER 和 SENTINEL_OBSERVER ,前者仅由领头 Sentinel 执行(一个 Sentinel),而后者由监视同一个 master 的所有 Sentinel 执行(多个 Sentinel)。










本文转自 chengxuyonghu 51CTO博客,原文链接:http://blog.51cto.com/6226001001/1904067,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章