zoukankan      html  css  js  c++  java
  • redis+keepalived实现高可用

    redis+keepalived实现高可用

    Redis简介:

    Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。

    redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

    设计思路:
    redis 主和 redis从  正常同步;

    redis主keepalived 启动,执行redis_master.sh脚本,vip在自己身上;

    redis 从keepalived 启动,执行redis_slave.sh脚本;

    redis主服务关闭,则redis主执行redis_fault.sh脚本,vip落在redis 从上,redis从执行redis_master.sh脚本,变成主;

    redis主服务开启,则redis主执行redis_slave.sh脚本变成从,vip还在redis 从上,还是主;

    redis从服务关闭,则redis从执行redis_fault.sh脚本,vip落在redis主上,redis主执行redis_master.sh脚本,变成主;

    redis从服务开启,则redis从执行redis_slave.sh脚本变成从,vip还在redis主上,redis主继续做主,此时为redis初试主从状态;

     

    通过keepalived的自定义脚本功能监控本机的redis服务状态,当监控脚本检测到redis服务出现异常时,则改变本机keepalived的优先级,同时这会导致master/backup角色的变化,而keepalived在角色变化时也会触发一些机制执行相关脚本,这就为我们改变redis的master/slave状态提供了机会,这样做的目的是为了是redis的master/slave直接的数据保持一致。

    在keepalived+redis的使用过程中有四种情况:

     1 一种是keepalived挂了,同时redis也挂了,这样的话直接VIP飘走之后,是不需要进行redis数据同步的,因为redis挂了,你也无法去master上同步,不过会损失已经写在master上却还没同步到slave上面的这部分数据。

     2 另一种是keepalived挂了,redis没挂,这时候VIP飘走后,redis的master/slave还是老的对应关系,如果不变化的话会把数据写入redis slave中,从而不会同步到master上去,这就要借助监控脚本反转redis的master/slave关系。这时候就要预留一点时间进行数据同步,然后反转master/slave。

     3 还有一种是keepalived没挂,redis挂了,这时候根据监控脚本会检测到redis挂了,并且降低keepalived master的优先级,同样会导致VIP飘走,情况和第二种一样,也是需要进行数据同步,然后反转当前redis的master/slave关系的。

     4 随后一种是keepalived没挂,redis也没挂,大吉大利啊,什么都不用操作。

    搭建环境:

    1、 操作系统

    Oracle Linux Server release 6.6

    2、 Keepalived

    keepalived-1.2.15

    3、 Redis

    redis-3.0.6

    4、 IP规划

    192.168.100.151  redis01

    192.168.100.152  redis02

    192.168.100.150  VIP

    一、    安装redis(master和slaves安装步骤相同,只是配置稍有不同)

    1、安装步骤:

    cd /opt

    tar –zxvf redis-3.0.6.tar.gz

    cd redis-3.0.6

    cd src

    make && make install

    2、修改配置:

    # vi /opt/redis-3.0.6/redis.conf (master)

    把daemonize no 修改为daemonize yes

    目的是可以在后台执行redis-server

    # vi /opt/redis-3.0.6/redis.conf  (slaves)

    把daemonize no 修改为daemonize yes

    增加:

    slaveof 192.168.100.151 6379

    3、设置开机启动

    #vi /etc/rc.d/init.d/redis

    #!/bin/sh 

    #chkconfig: 345 86 14 

    #description: Startup and shutdown script for Redis 

    PROGDIR=/opt/redis-3.0.6/src #安装路径 

    PROGNAME=redis-server 

    DAEMON=$PROGDIR/$PROGNAME 

    CONFIG=/opt/redis-3.0.6/redis.conf 

    PIDFILE=/var/run/redis.pid 

    DESC="redis daemon" 

    SCRIPTNAME=/etc/rc.d/init.d/redis    

    start() 

             if test -x $DAEMON 

             then 

            echo -e "Starting $DESC: $PROGNAME" 

                       if $DAEMON $CONFIG 

                       then 

                                echo -e "OK" 

                       else 

                                echo -e "failed" 

                       fi 

             else 

                       echo -e "Couldn't find Redis Server ($DAEMON)" 

             fi 

    stop() 

             if test -e $PIDFILE 

             then 

                       echo -e "Stopping $DESC: $PROGNAME" 

                       if kill `cat $PIDFILE` 

                       then 

                                echo -e "OK" 

                       else 

                                echo -e "failed" 

                       fi 

             else 

                       echo -e "No Redis Server ($DAEMON) running" 

             fi 

    }     

    restart() 

        echo -e "Restarting $DESC: $PROGNAME" 

        stop 

             start 

    }     

    list() 

             ps aux | grep $PROGNAME 

    }   

    case $1 in 

             start) 

                       start 

            ;; 

             stop) 

            stop 

            ;; 

             restart) 

            restart 

            ;; 

             list) 

            list 

            ;; 

      

             *) 

            echo "Usage: $SCRIPTNAME {start|stop|restart|list}" >&2 

            exit 1 

            ;; 

    esac 

    exit 0

    #chmod 744 /etc/rc.d/init.d/redis

    #chkconfig --add redis  

    #chkconfig --level 345 redis on  

    #chkconfig --list redis 

    4、redis主从测试

    #主服务器

    redis-cli -p 6379 set hello world

    #从服务器

    redis-cli -p 6379 get hello

    “world”

    #主服务器

    redis-cli -p 6379 set hello2 world2

    #从服务器

    redis-cli -p 6379 get hello2

    “world2”

    redis-cli -p 6379 set hello world

    (error) READONLY You can’t write against a read only slave.

    成功配置主从redis服务器,由于配置中有一条从服务器是只读的,所以从服务器没法设置数据,只可以读取数据。

    二、    安装keepalived

    1、安装keepalived步骤

    cd /opt

    tar –zxvf keepalived-1.2.15.tar.gz

    cd keepalived-1.2.15

    ln -s /usr/src/kernels/3.8.13-44.1.1.el6uek.x86_64 /usr/src/linux

    3.8.13-44.1.1.el6uek.x86_64可以由uname –a 查询得到

    ./configure --prefix=/usr/local/keepalived --with-kernel-dir=/usr/src/linux -enable-sha1

    出现报错:

    解决:

    yum install openssl-devel

    重新执行

    ./configure --prefix=/usr/local/keepalived --with-kernel-dir=/usr/src/linux -enable-sha1

    make && make install

    复制keepalived相关文件

    [root@redis01 keepalived-1.2.15]# cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/keepalived

    [root@redis01 keepalived-1.2.15]#cp /usr/local/keepalived/sbin/keepalived /usr/sbin/keepalived

    [root@redis01 keepalived-1.2.15]# cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/keepalived

    [root@redis01 keepalived-1.2.15]# mkdir /etc/keepalived

    [root@redis01keepalived-1.2.15]#cp /usr/local/keepalived/etc/keepalived/samples/keepalived.conf.virtualhost /etc/keepalived/keepalived.conf

    [root@redis01 keepalived-1.2.15]#

    2、设置开机自启动

    chkconfig –add keepalived

    chkconfig keepalived on

    chkconfig –list keepalived

    三、    通过Keepalived实现Redis Failover自动故障切换

    1、修改Master和Slave的/etc/hosts文件

    [root@redis rc.d]#cat /etc/hosts   (Master)

    192.168.1.151 redis01

    192.168.1.152 redis02

    [root@redis rc.d]#cat /etc/sysconfig/network

    NETWORKING=yes

    HOSTNAME=redis01

    [root@redis rc.d]#cat /etc/hosts   (slaves)

    192.168.1.151 redis01

    192.168.1.152 redis02

    [root@redis-slave linux]# cat /etc/sysconfig/network

    NETWORKING=yes

    HOSTNAME=redis02

    修改完主机名重启机器生效

    2、默认安装完成keepalived之后是没有配置文件的,因此我们需要手动创建:

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

    [root@redis  linux]# vim /etc/keepalived/keepalived.conf

    global_defs {

       notification_email {

         test@163.com

       }

       notification_email_from keepalived@redis01

       router_id redis01

    }

    vrrp_script chk_redis {

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

        interval 1

    }

    vrrp_instance mes_Redis {

        state MASTER

        interface eth0

        garp_master_delay 10

        smtp_alert

        virtual_router_id 3

        priority 100

        nopreempt

        advert_int 1

        authentication {

            auth_type PASS

            auth_pass 1111

        }

        virtual_ipaddress {

            192.168.100.150

        }

        track_script {

            chk_redis

        }

        notify_master /etc/keepalived/scripts/redis_master.sh

        notify_backup /etc/keepalived/scripts/redis_slave.sh

        notify_fault  /etc/keepalived/scripts/redis_fault.sh

        notify_stop   /etc/keepalived/scripts/redis_stop.sh

    }

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

    [root@redis-slave linux]# vim /etc/keepalived/keepalived.conf

    global_defs {

       notification_email {

         test@163.com

       }

       notification_email_from keepalived@redis02

       router_id redis02

    }

    vrrp_script chk_redis {

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

        interval 1

    }

    vrrp_instance mes_Redis {

        state BACKUP

        interface eth0

        garp_master_delay 10

        smtp_alert

        virtual_router_id 3

        priority 90

        nopreempt

        advert_int 1

        authentication {

            auth_type PASS

            auth_pass 1111

        }

        virtual_ipaddress {

            192.168.100.150

        }

        track_script {

            chk_redis

        }

        notify_master /etc/keepalived/scripts/redis_master.sh

        notify_backup /etc/keepalived/scripts/redis_slave.sh

        notify_fault  /etc/keepalived/scripts/redis_fault.sh

        notify_stop   /etc/keepalived/scripts/redis_stop.sh

    }

    注:修改M,B服务器的  state BACKUP 都为【备】类型,同时设置 nopreempt  设置为不抢夺VIP,然后先启动M服务器,M服务器会成为【主】,然后启动B服务器,由于M的优先级高【priority 100】 所以B不会抢夺VIP,这时M宕机,B成为【主】,接着M恢复正常,由于设置了nopreempt 所以M不会抢夺VIP,B继续为【主】而M为【备】。想要M宕机恢复后继续为【主】,注释nopreempt即可。

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

    mkdir /etc/keepalived/scripts

    vim /etc/keepalived/scripts/redis_check.sh

    #!/bin/bash

    ALIVE=`/opt/redis-3.0.6/src/redis-cli PING`

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

      echo $ALIVE

      exit 0

    else

      echo $ALIVE

      exit 1

    fi

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

     notify_master /etc/keepalived/scripts/redis_master.sh

     notify_backup /etc/keepalived/scripts/redis_slave.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="/opt/redis-3.0.6/src/redis-cli"

    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 192.168.100.152 6379 >> $LOGFILE  2>&1

    sleep 10 #延迟10秒以后待数据同步完成后再取消同步状态

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

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

     

    vim /etc/keepalived/scripts/redis_slave.sh

    #!/bin/bash

    REDISCLI="/opt/redis-3.0.6/src/redis-cli"

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

    echo "[backup]" >> $LOGFILE

    date >> $LOGFILE

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

    sleep 15 #延迟15秒待数据被对方同步完成之后再切换主从角色

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

    $REDISCLI SLAVEOF 192.168.100.152 6379 >> $LOGFILE  2>&1

     

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

    vim /etc/keepalived/scripts/redis_master.sh

    #!/bin/bash

    REDISCLI="/opt/redis-3.0.6/src/redis-cli"

    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 192.168.100.151 6379 >> $LOGFILE  2>&1

    sleep 10 #延迟10秒以后待数据同步完成后再取消同步状态

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

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

    vim /etc/keepalived/scripts/redis_slave.sh

    #!/bin/bash

    REDISCLI="/opt/redis-3.0.6/src/redis-cli"

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

    echo "[backup]" >> $LOGFILE

    date >> $LOGFILE

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

    sleep 15 #延迟15秒待数据被对方同步完成之后再切换主从角色

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

    $REDISCLI SLAVEOF 192.168.10.151 6379 >> $LOGFILE  2>&1

     

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

    vim /etc/keepalived/scripts/redis_fault.sh

    #!/bin/bash

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

    echo "[fault]" >> $LOGFILE

    date >> $LOGFILE

     

    vim /etc/keepalived/scripts/redis_stop.sh

    #!/bin/bash

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

    echo "[stop]" >> $LOGFILE

    date >> $LOGFILE

     

    在Master与Slave给脚本都加上可执行权限:

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

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

     1.启动Master上的Redis

    [root@redis bin]# service redis start

    2.启动Slave上的Redis

    [root@redis bin]# service redis start

    3.启动Master上的Keepalived

    service keepalived start

    4.启动Slave上的Keepalived

    service keepalived start 

    5.尝试通过VIP连接Redis:

    [root@redis bin]#pwd

    /opt/redis-3.0.6/src

    [root@redis bin]# ./redis-cli -h 192.168.100.150 info

    role:master

    slave0:192.168.100.152,6379,online

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

    6.尝试插入一些数据:

    [root@redis bin]# ./redis-cli -h 192.168.100.150 SET Hello Redis 

    从VIP读取数据

    [root@redis bin]# ./redis-cli -h 192.168.100.150 GET Hello

    "Redis"

    从Master读取数据

    [root@redis bin]# ./redis-cli -h 192.168.100.151  GET Hello

    "Redis"

    从Slave读取数据

    [root@redis-slave bin]# ./redis-cli -h 192.168.100.152  GET Hello

    "Redis"

    下面,模拟故障产生:

    将Master上的Redis进程杀死:

    [root@redis bin]# ./redis-cli shutdown

    查看Master上的Keepalived日志

    [root@redis01 scripts]# tail /var/log/keepalived-redis-state.log

    [fault]

    Thu Sep 27 08:29:01 CST 2016

    同时Slave上的日志显示:

    [root@redis02 scripts]# tail /var/log/keepalived-redis-state.log

    [master]

    Thu Nov 15 12:06:04 CST 2016

    Being master....

    Run SLAVEOF cmd ...

    OK

    Run SLAVEOF NO ONE cmd ...

    OK

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

    ./redis-cli -h 192.168.100.150 info

    ./redis-cli -h 192.168.100.152 info

     role:master

    然后我们恢复Master的Redis进程

    主变成slave

    然后把152redis停掉

    151恢复主的角色,在把152redis开启

    恢复151是主,152是备

    自动切换成功!

  • 相关阅读:
    CodeForces 510C Fox And Names (拓扑排序)
    Codeforces 1153D Serval and Rooted Tree (简单树形DP)
    HDU 6437 Problem L.Videos (最大费用)【费用流】
    Luogu P3381 (模板题) 最小费用最大流
    Codeforces 741B Arpa's weak amphitheater and Mehrdad's valuable Hoses (并查集+分组背包)
    Codeforces 1144F Graph Without Long Directed Paths (DFS染色+构造)
    HDU 2204 Eddy's 爱好 (容斥原理)
    Codeforces 939E Maximize! (三分 || 尺取)
    Codeforces 938D. Buy a Ticket (最短路+建图)
    CodeForces 959E Mahmoud and Ehab and the xor-MST (MST+找规律)
  • 原文地址:https://www.cnblogs.com/chenjunjie/p/6187983.html
Copyright © 2011-2022 走看看