redis + keepalived 双主模型

redis + keepalived 双主模型

架构图:

redis11.png  

1.vip默认绑定在redis主上,由redis主提供服务,redis从为备用节点。(实际上提供服务的只是vip)
2.当redis主挂掉,vip会默认漂移至redis从。由redis从提供服务,redis主已经挂掉。
3.当redis主已经恢复,redis从继续提供服务和挂载vip.
4.当redis从挂掉,vip会漂移到redis主上。当你修复好redis从,默认他会同步数据,然后变成备用节点。
5.只要redis主从不全挂,基本上是不会影响的。从而实现了双主的模型。(此双主并不是同时写数据,只是逻辑上的双主)

操作系统:centos 6.6 64bit

keepalived + redis主 : 192.168.155.205

keepalived + redis从 : 192.168.155.206

vip:192.168.155.207

1.两台redis环境准备工作(两台都做)

[root@web01 ~]# yum install vim gcc telnet wget lrzsz openssl openssl-devel openssl-clients ntpdate -y
[root@web01 ~]# sed -i 's@SELINUX=enforcing@SELINUX=disabled@g' /etc/sysconfig/selinux
[root@web01 ~]# setenforce 0
[root@web01 ~]# /etc/init.d/iptables stop
[root@web01 ~]# chkconfig iptables off
[root@web01 ~]# ntpdate time.nist.gov
分别修改主机名为redis_master 和 redis_slave
[root@web01 ~]# vim /etc/sysconfig/network
HOSTNAME=redis_master
[root@web02 ~]# vim /etc/sysconfig/network
HOSTNAME=redis_slave

两台机器分别重启(不重启机器也可以,使用hostname修改主机名,然后使用bash命令.)

2.两台机器分别安装redis(两台都做)

[root@redis_master ~]# wget http://download.redis.io/releases/redis-3.2.0.tar.gz
[root@redis_master ~]# tar xf redis-3.2.0.tar.gz
[root@redis_master ~]# mkdir -p /usr/local/redis
[root@redis_master ~]# mv redis-3.2.0/*  /usr/local/redis
[root@redis_master redis]# cd /usr/local/redis
[root@redis_master redis]# make
[root@redis_master src]# cd src && make install
[root@redis_master src]# cd /usr/local/redis
[root@redis_master redis]# cp redis.conf   /etc/
[root@redis_master redis]# mkdir  -p  /redis/log      #日志目录
[root@redis_master redis]# mkdir  -p   /redis/run     #pid文件目录
[root@redis_master redis]# mkdir  -p   /redis/data    #本地快照数据库存放目录
[root@redis_master redis]# vi /etc/redis.conf         #编辑
daemonize yes  #设置后台启动redis
[root@redis_master redis]# sysctl vm.overcommit_memory=1
[root@redis_master redis]# echo never > /sys/kernel/mm/transparent_hugepage/enabled
[root@redis_master redis]# vi /etc/sysctl.conf        #编辑,在最后一行添加下面代码
vm.overcommit_memory = 1
[root@redis_master redis]# sysctl -p #使设置立即生效

3.设置redis开机自动启动

vi /etc/init.d/redis   #编辑,添加以下代码
#!/bin/sh
# chkconfig:   2345 90 10
# description:  Redis is a persistent key-value database
# redis    Startup script for redis processe
# processname: redis
redis_path="/usr/local/bin/redis-server"
redis_conf="/etc/redis.conf"
redis_pid="/redis/run/redis.pid"
# Source function library.
. /etc/rc.d/init.d/functions
[ -x $redis_path ] || exit 0
RETVAL=0
prog="redis"
# Start daemons.
start() {
if [ -e $redis_pid -a ! -z $redis_pid ];then
echo $prog" already running...."
exit 1
fi
echo -n $"Starting $prog "
# Single instance for all caches
$redis_path $redis_conf
RETVAL=$?
[ $RETVAL -eq 0 ] && {
touch /var/lock/subsys/$prog
success $"$prog"
}
echo
return $RETVAL
}
# Stop daemons.
stop() {
echo -n $"Stopping $prog "
killproc -d 10 $redis_path
echo
[ $RETVAL = 0 ] && rm -f $redis_pid /var/lock/subsys/$prog
RETVAL=$?
return $RETVAL
}
# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status $prog
RETVAL=$?
;;
restart)
stop
start
;;
condrestart)
if test "x`pidof redis`" != x; then
stop
start
fi
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart}"
exit 1
esac
exit $RETVAL
[root@redis_master redis]# chmod 755 /etc/init.d/redis        #添加脚本执行权限
[root@redis_master redis]# chkconfig --add redis              #添加开启启动
[root@redis_master  redis]# chkconfig --level 2345 redis on  #设置启动级别
[root@redis_master redis]# chkconfig --list redis             #查看启动级别
[root@redis_master redis]# service redis restart              #重新启动redis
Stopping redis                                             [  OK  ]
Starting redis                                             [  OK  ]

4.redis主从配置文件

redis_master配置文件

[root@redis_master redis]# vim /etc/redis.conf
protected-mode no    #必须要加的参数,在3.2版本
daemonize yes
pidfile /redis/run/redis.pid
port 6379
tcp-backlog 511
timeout 1800
tcp-keepalive 0
loglevel verbose
logfile "/redis/log/redis.log"
databases 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir ./
slaveof 192.168.155.206 6379
slave-read-only yes
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
slave-priority 100
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes

lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-entries 512
list-max-ziplist-value 64
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes

redis_slave配置文件

[root@redis_slave  redis]# vim /etc/redis.conf
protected-mode no    #必须要加的参数,在3.2版本
daemonize yes
pidfile /redis/run/redis.pid
port 6379
tcp-backlog 511
timeout 1800
tcp-keepalive 0
loglevel verbose
logfile "/redis/log/redis.log"
databases 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir ./
slaveof 192.168.155.205 6379
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
slave-priority 100
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec

no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-entries 512
list-max-ziplist-value 64
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes

然后重启redis,现在redis都配置了双主,但是他们现在都不可以写入,必须要配置keepalived,有redis主,才可以写入。

小提示:经过最后面的测试,redis.conf配置文件,可以省略2个配置文件不写,也可以测试成功,配置如下:

slaveof 192.168.155.206 6379
slave-read-only yes

5.redis配置文件详解

daemonize yes                      
#以后台daemon方式运行redis
pidfile "/var/run/redis.pid"       
#redis以后台运行,默认pid文件路径/var/run/redis.pid
port 6379                          
#默认端口
bind 127.0.0.1                      
#默认绑定本机所有ip地址,为了安全,可以只监听内网ip
timeout 300                         
#客户端空闲n秒后断开连接,单位为秒;默认是 0 表示不断开
loglevel verbose                   
#设置日志级别,支持四个级别:debug、notice、verbose、warning
logfile stdout                      
#日志记录方式,默认为标准输出,logs不写文件,输出到空设备/deb/null   
logfile "/redis/log/redis.log"      
#可以指定日志文件路径
databases 16                        
#开启数据库的数量
save 900 1
save 300 10
save 60 10000  
创建本地数据库快照,格式:save * *
900秒内,执行1次写操作
300秒内,执行10次写操作
60秒内,执行10000次写操作

rdbcompression yes                  
#启用数据库lzf压缩,也可以设置为no
dbfilename dump.rdb                 
#本地快照数据库名称
dir "/redis/6369/"                  
#本地快照数据库存放目录
requirepass 123456                  
#设置redis数据库连接密码
maxclients 10000                    
#同一时间最大客户端连接数,0为无限制
maxmemory 1024MB                    
#设定redis最大使用内存,值要小于物理内存,必须设置
appendonly yes                      
#开启日志记录,相当于MySQL的binlog
appendfilename "appendonly.aof"     
#日志文件名,注意:不是目录路径

appendfsync everysec                
#每秒执行同步,还有两个参数always、no一般设置为everysec,相当于MySQL事物日志的写方式
slave-serve-stale-data yes          
#当主master服务器挂机或主从复制在进行时,是否依然可以允许客户访问可能过期的数据。
#在"yes"情况下,slave继续向客户端提供只读服务,有可能此时的数据已经过期;
#在"no"情况下,任何向此server发送的数据请求服务(包括客户端和此server的slave)都将被告知"error"
slave-read-only yes                 
#slave是否为"只读",强烈建议为"yes"
repl-ping-slave-period 10           
#slave向指定的master发送ping消息的时间间隔(秒),默认为10
repl-timeout 60                     
#slave与master通讯中,最大空闲时间,默认60秒.超时将导致连接关闭 
repl-disable-tcp-nodelay no         
#slave与master的连接,是否禁用TCP nodelay选项。"yes"表示禁用
#那么socket通讯中数据将会以packet方式发送(packet大小受到socket buffer限制)。
1. Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程
    daemonize no
2. 当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,可以通过pidfile指定
    pidfile /var/run/redis.pid
3. 指定Redis监听端口,默认端口为6379,作者在自己的一篇博文中解释了为什么选用6379作为默认端口,
    因为6379在手机按键上MERZ对应的号码,而MERZ取自意大利歌女Alessia Merz的名字
    port 6379
4. 绑定的主机地址
    bind 127.0.0.1
5.当 客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能
    timeout 300
6. 指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,默认为verbose
    loglevel verbose
7. 日志记录方式,默认为标准输出,如果配置Redis为守护进程方式运行,
    而这里又配置为日志记录方式为标准输出,则日志将会发送给/dev/null
    logfile stdout
8. 设置数据库的数量,默认数据库为0,可以使用SELECT <dbid>命令在连接上指定数据库id
    databases 16
9. 指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合
    save <seconds> <changes>
    Redis默认配置文件中提供了三个条件:
    save 900 1
    save 300 10
    save 60 10000
    分别表示900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改以及60秒内有10000个更改。
 
10. 指定存储至本地数据库时是否压缩数据,默认为yes,Redis采用LZF压缩,如果为了节省CPU时间,
    可以关闭该选项,但会导致数据库文件变的巨大
    rdbcompression yes
11. 指定本地数据库文件名,默认值为dump.rdb
    dbfilename dump.rdb
12. 指定本地数据库存放目录
    dir ./
13. 设置当本机为slav服务时,设置master服务的IP地址及端口,在Redis启动时,
    它会自动从master进行数据同步
    slaveof <masterip> <masterport>
14. 当master服务设置了密码保护时,slav服务连接master的密码
    masterauth <master-password>
15. 设置Redis连接密码,如果配置了连接密码,客户端在连接Redis时需要通过AUTH <password>命令提供密码,默认关闭
    requirepass foobared
16. 设置同一时间最大客户端连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数,
    如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,
    Redis会关闭新的连接并向客户端返回max number of clients reached错误信息
    maxclients 128
17. 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key,
当此方法处理 后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。
Redis新的vm机制,会把Key存放内存,Value会存放在swap区
    maxmemory <bytes>
18. 指定是否在每次更新操作后进行日志记录,Redis在默认情况下是异步的把数据写入磁盘,如果不开启,
可能会在断电时导致一段时间内的数据丢失。因为 redis本身同步数据文件是按上面save条件来同步的,
所以有的数据会在一段时间内只存在于内存中。默认为no
    appendonly no
19. 指定更新日志文件名,默认为appendonly.aof
     appendfilename appendonly.aof
20. 指定更新日志条件,共有3个可选值: 
    no:表示等操作系统进行数据缓存同步到磁盘(快) 
    always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全) 
    everysec:表示每秒同步一次(折衷,默认值)

6.keepalived安装(两台机器都同时安装)

[root@redis_master ~]# wget http://www.keepalived.org/software/keepalived-1.2.20.tar.gz  
[root@redis_master ~]# tar -xf keepalived-1.2.20.tar.gz
[root@redis_master ~]# cd keepalived-1.2.20
[root@redis_master keepalived-1.2.20]# ./configure --prefix=/usr/local/keepalived 
[root@redis_master keepalived-1.2.20]# make && make install
[root@redis_master keepalived-1.2.20]# cp /usr/local/keepalived/sbin/keepalived   /usr/sbin/
[root@redis_master keepalived-1.2.20]# cp /usr/local/keepalived/etc/sysconfig/keepalived   /etc/sysconfig/
[root@redis_master keepalived-1.2.20]# cp  /usr/local/keepalived/etc/rc.d/init.d/keepalived  /etc/init.d/
[root@redis_master  keepalived-1.2.20]#  cp /usr/local/keepalived/etc/keepalived/keepalived.conf  /etc/keepalived/
[root@redis_master keepalived-1.2.20]# mkdir -p /etc/keepalived/log/
[root@redis_master keepalived-1.2.20]# mkdir -p /etc/keepalived/scripts/
添加日志
[root@redis_master keepalived-1.2.20]# vim /etc/sysconfig/keepalived
KEEPALIVED_OPTIONS="-D"
修改为
KEEPALIVED_OPTIONS="-D -d -S 0"
[root@redis_master keepalived-1.2.20]# vi /etc/rsyslog.conf
加入如下配置:
#keepalived -S 0
local0.* /var/log/keepalived.log
重启日志服务
[root@redis_master keepalived-1.2.20]# /etc/init.d/rsyslog restart
监测日志文件是否生成
[root@redis_master keepalived-1.2.20]# ll /var/log/keepalived.log
-rw-------. 1 root root 0 Jun 21 19:46 /var/log/keepalived.log

keepalived已经安装完毕

7.keepalived配置文件

redis主上keepalived配置文件

global_defs {
            lvs_id LVS_redis 80
           smtp_connect_timeout 30
        }
vrrp_script chk_redis { 
        script "sh /etc/keepalived/scripts/redis_check.sh"
        interval 1                                   
        weight 2
} 
 
vrrp_instance VI_1 { 
        state MASTER                         
        interface eth1                    
        virtual_router_id 60
        unicast_src_ip 192.168.155.205
        unicast_peer {
            192.168.155.206
        }
        priority 200     
        advert_int 1  
        track_script { 
            chk_redis                     
        } 
        virtual_ipaddress { 
             192.168.155.207                     
        }
        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 
}

redis从上keepalived配置文件

global_defs {
            lvs_id LVS_redis 80
           smtp_connect_timeout 30
        }
vrrp_script chk_redis { 
        script "sh /etc/keepalived/scripts/redis_check.sh"
        interval 1                                    
        weight 2
} 
 
vrrp_instance VI_1 { 
        state MASTER                       
        interface eth1                         
        virtual_router_id 60
        priority 200       
        unicast_src_ip 192.168.155.206
        unicast_peer {
           192.168.155.205
        }
        advert_int 1  
        track_script { 
            chk_redis                     
        } 
        virtual_ipaddress { 
             192.168.155.207                    
        }
        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配置文件。

redis_master

redis_check.sh文件如下:

#!/bin/bash

SERV=keepalived
CHECK_TIME=2

check() {
    /usr/local/bin/redis-cli  ping > /dev/null 2>&1

    ret=$?

    if [ $ret -ne 0 ];then
        return $ret;

    fi
}

while [ $CHECK_TIME -ne 0 ];do
    let "CHECK_TIME -= 1"

    check
    REDIS_OK=$?

    if [ $REDIS_OK -eq 0 ];then
        exit $REDIS_OK
    else

        if [ $CHECK_TIME -eq 0 ];then
            /etc/init.d/$SERV stop
            exit $REDIS_OK
        fi
    fi
done

redis_stop.sh文件如下:
#!/bin/bash
###/etc/keepalived/scripts/redis_stop.sh
REDISCLI="/usr/local/bin/redis-cli "
LOGFILE="/etc/keepalived/log/redis-state.log"
pid=$$
 
echo "Run redis_stop.sh" >> $LOGFILE
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master]" >> $LOGFILE
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master] Being slave state..." >> $LOGFILE 2>&1
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[slaver] Run 'SLAVEOF 192.168.155.206 6379'" >> $LOGFILE
$REDISCLI SLAVEOF  192.168.155.206 6379 >> $LOGFILE  2>&1
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[slaver] slave connect to 192.168.155.206  ok..." >> $LOGFILE

redis_fault.sh文件如下:
#!/bin/bash
###/etc/keepalived/scripts/redis_fault.sh
REDISCLI="/usr/local/bin/redis-cli "
LOGFILE="/etc/keepalived/log/redis-state.log"
pid=$$
 
echo "Run redis_fault.sh" >> $LOGFILE
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master]" >> $LOGFILE
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master] Being slave state..." >> $LOGFILE 2>&1
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[slaver] Run 'SLAVEOF 192.168.155.206 6379'" >> $LOGFILE
$REDISCLI SLAVEOF  192.168.155.206 6379 >> $LOGFILE  2>&1
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[slaver] slave connect to 192.168.155.206  ok..." >> $LOGFILE

redis_backup.sh文件如下:
#!/bin/bash
###/etc/keepalived/scripts/redis_backup.sh
REDISCLI="/usr/local/bin/redis-cli "
LOGFILE="/etc/keepalived/log/redis-state.log"
pid=$$
 
echo "Run redis_backup.sh" >> $LOGFILE
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master]" >> $LOGFILE
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master] Being slave state..." >> $LOGFILE 2>&1
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[slaver] Run 'SLAVEOF 192.168.155.206 6379'" >> $LOGFILE
$REDISCLI SLAVEOF  192.168.155.206 6379 >> $LOGFILE  2>&1
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[slaver] slave connect to 192.168.155.206  ok..." >> $LOGFILE

redis_master.sh文件如下:
#!/bin/bash
###/etc/keepalived/scripts/redis_master.sh
REDISCLI="/usr/local/bin/redis-cli "
LOGFILE="/etc/keepalived/log/redis-state.log"
pid=$$
 
echo "Run redis_master.sh" >> $LOGFILE
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[slaver]" >> $LOGFILE
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[slaver] Run 'SLAVEOF 192.168.88.206 6379'" >> $LOGFILE
$REDISCLI SLAVEOF 192.168.155.206  6379 >> $LOGFILE  2>&1
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master] Run slaveof no one,close master/slave" >> $LOGFILE
$REDISCLI SLAVEOF NO ONE >> $LOGFILE 2>&1
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master] wait other slave connect...." >> $LOGFILE

redis_slave

redis_check.sh文件如下:

#!/bin/bash

SERV=keepalived
CHECK_TIME=2

check() {
    /usr/local/bin/redis-cli  ping > /dev/null 2>&1

    ret=$?

    if [ $ret -ne 0 ];then
        return $ret;

    fi
}

while [ $CHECK_TIME -ne 0 ];do
    let "CHECK_TIME -= 1"

    check
    REDIS_OK=$?

    if [ $REDIS_OK -eq 0 ];then
        exit $REDIS_OK
    else

        if [ $CHECK_TIME -eq 0 ];then
            /etc/init.d/$SERV stop
            exit $REDIS_OK
        fi
    fi
done
redis_stop.sh文件如下:
#!/bin/bash
###/etc/keepalived/scripts/redis_stop.sh
REDISCLI="/usr/local/bin/redis-cli "
LOGFILE="/etc/keepalived/log/redis-state.log"
pid=$$
 
echo "Run redis_stop.sh" >> $LOGFILE
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master]" >> $LOGFILE
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master] Being slave state..." >> $LOGFILE 2>&1
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[slaver] Run 'SLAVEOF 192.168.155.205 6379'" >> $LOGFILE
$REDISCLI SLAVEOF  192.168.155.205 6379 >> $LOGFILE  2>&1
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[slaver] slave connect to 192.168.155.205  ok..." >> $LOGFILE
redis_fault.sh文件如下:
#!/bin/bash
###/etc/keepalived/scripts/redis_fault.sh
REDISCLI="/usr/local/bin/redis-cli "
LOGFILE="/etc/keepalived/log/redis-state.log"
pid=$$
 
echo "Run redis_fault.sh" >> $LOGFILE
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master]" >> $LOGFILE
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master] Being slave state..." >> $LOGFILE 2>&1
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[slaver] Run 'SLAVEOF 192.168.155.205 6379'" >> $LOGFILE
$REDISCLI SLAVEOF  192.168.155.205 6379 >> $LOGFILE  2>&1
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[slaver] slave connect to 192.168.155.205  ok..." >> $LOGFILE
redis_backup.sh文件如下:
#!/bin/bash
###/etc/keepalived/scripts/redis_backup.sh
REDISCLI="/usr/local/bin/redis-cli "
LOGFILE="/etc/keepalived/log/redis-state.log"
pid=$$
 
echo "Run redis_backup.sh" >> $LOGFILE
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master]" >> $LOGFILE
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master] Being slave state..." >> $LOGFILE 2>&1
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[slaver] Run 'SLAVEOF 192.168.155.205 6379'" >> $LOGFILE
$REDISCLI SLAVEOF  192.168.155.205 6379 >> $LOGFILE  2>&1
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[slaver] slave connect to 192.168.155.205  ok..." >> $LOGFILE
redis_master.sh文件如下:
#!/bin/bash
###/etc/keepalived/scripts/redis_master.sh
REDISCLI="/usr/local/bin/redis-cli "
LOGFILE="/etc/keepalived/log/redis-state.log"
pid=$$
 
echo "Run redis_master.sh" >> $LOGFILE
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[slaver]" >> $LOGFILE
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[slaver] Run 'SLAVEOF 192.168.88.205 6379'" >> $LOGFILE
$REDISCLI SLAVEOF 192.168.155.205  6379 >> $LOGFILE  2>&1
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master] Run slaveof no one,close master/slave" >> $LOGFILE
$REDISCLI SLAVEOF NO ONE >> $LOGFILE 2>&1
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master] wait other slave connect...." >> $LOGFILE
[root@redis_master scripts]# cd /etc/keepalived/scripts/
[root@redis_master scripts]# chmod +x *
[root@redis_master scripts]# /etc/init.d/keepalivded restart

测试阶段:

1.    redis主从都启动keepalived

redis_master
[root@redis_master scripts]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:d6:63:b6 brd ff:ff:ff:ff:ff:ff
    inet 192.168.155.205/24 brd 192.168.155.255 scope global eth1
    inet 192.168.155.207/32 scope global eth1
    inet6 fe80::20c:29ff:fed6:63b6/64 scope link 
       valid_lft forever preferred_lft forever

redis_slave
[root@redis_slave scripts]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:46:38:94 brd ff:ff:ff:ff:ff:ff
    inet 192.168.155.206/24 brd 192.168.155.255 scope global eth1
    inet6 fe80::20c:29ff:fe46:3894/64 scope link 
       valid_lft forever preferred_lft forever

2.    测试主从同步

redis_master
[root@redis_master scripts]# redis-cli
127.0.0.1:6379> set laopo hyl
OK
127.0.0.1:6379> get laopo
"hyl"
127.0.0.1:6379>
redis_slave
[root@redis_slave ~]# redis-cli 
127.0.0.1:6379> get laopo
"hyl"
127.0.0.1:6379>

redis主从已经测试成功

可以多设置几个值(在down之前):

127.0.0.1:6379> set 11 22
OK
127.0.0.1:6379> set 22 33
OK
127.0.0.1:6379> set 33 44
OK
127.0.0.1:6379> set 44 55
OK
127.0.0.1:6379> get 11
"22"
127.0.0.1:6379> get 22
"33"
127.0.0.1:6379> get 33
"44"
127.0.0.1:6379> get 44
"55"

3.测试redis主down

redis_master
[root@redis_master ~]# /etc/init.d/redis stop
[root@redis_master ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:d6:63:b6 brd ff:ff:ff:ff:ff:ff
    inet 192.168.155.205/24 brd 192.168.155.255 scope global eth1
    inet6 fe80::20c:29ff:fed6:63b6/64 scope link 
       valid_lft forever preferred_lft forever
[root@redis_master ~]# ss -ln
State       Recv-Q Send-Q      Local Address:Port     Peer Address:Port 
LISTEN      0      128        :::22           :::*     
LISTEN      0      128         *:22           *:*     
LISTEN      0      100        ::1:25           :::*     
LISTEN      0      100        127.0.0.1:25        *:*     
LISTEN      0      50         *:3306          *:*
redis_slave
[root@redis_slave ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:46:38:94 brd ff:ff:ff:ff:ff:ff
    inet 192.168.155.206/24 brd 192.168.155.255 scope global eth1
    inet 192.168.155.207/32 scope global eth1
    inet6 fe80::20c:29ff:fe46:3894/64 scope link 
       valid_lft forever preferred_lft forever
[root@redis_slave ~]# ss -ln
State       Recv-Q Send-Q      Local Address:Port     Peer Address:Port 
LISTEN      0      128        :::22                   :::*     
LISTEN      0      128         *:22                  *:*     
LISTEN      0      100        ::1:25                  :::*     
LISTEN      0      100        127.0.0.1:25               *:*     
LISTEN      0      50         *:3306                  *:*
LISTEN      0      128        *:6379                     *:*             
LISTEN      0      128                :::6379         :::*

vip已经漂移至 redis_slave,测试redis主从是否切换;

redis_slave
[root@redis_slave ~]# redis-cli 
127.0.0.1:6379> set 123 123
OK
127.0.0.1:6379> get 123
"123"
127.0.0.1:6379> get 11
"22"
127.0.0.1:6379> get 22
"33"
127.0.0.1:6379> get 33
"44"
再down之前,多设置几个键值
127.0.0.1:6379> set 1010 1010
OK
127.0.0.1:6379> set 2020 2020
OK
127.0.0.1:6379> set 3030 3030
OK
127.0.0.1:6379> get 1010
"1010"
127.0.0.1:6379> get 2020
"2020"
127.0.0.1:6379> get 3030
"3030"
redis_master
[root@redis_master ~]# /etc/init.d/redis start
[root@redis_master ~]# /etc/init.d/keepalived start
Starting keepalived:                         [  OK  ]
[root@redis_master ~]# redis-cli 
127.0.0.1:6379> get 123
"123"
127.0.0.1:6379> get 11
"22"
127.0.0.1:6379> get 33
"44"
127.0.0.1:6379> get 44
"55"
127.0.0.1:6379> get 1010
"1010"
127.0.0.1:6379> get 2020
"2020"
127.0.0.1:6379> get 3030
"3030"

redis数据不会丢失,redis从立马会接管vip提供服务。redis主从角色互调。

4.redis主恢复后,一直处于slave状态,如果redis从down掉,redis主是否会重新夺取vip,并且数据自动同步回来。

redis_slave
[root@redis_slave ~]# /etc/init.d/redis stop
[root@redis_slave ~]# /etc/init.d/redis start
[root@redis_slave ~]# /etc/init.d/keepalived start
Starting keepalived:                    [  OK  ]
[root@redis_slave ~]# i a
bash: i: command not found
[root@redis_slave ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:46:38:94 brd ff:ff:ff:ff:ff:ff
    inet 192.168.155.206/24 brd 192.168.155.255 scope global eth1
    inet6 fe80::20c:29ff:fe46:3894/64 scope link 
       valid_lft forever preferred_lft forever
vip已经漂移至redis_master
redis_master
[root@redis_master ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:d6:63:b6 brd ff:ff:ff:ff:ff:ff
    inet 192.168.155.205/24 brd 192.168.155.255 scope global eth1
    inet 192.168.155.207/32 scope global eth1
    inet6 fe80::20c:29ff:fed6:63b6/64 scope link 
       valid_lft forever preferred_lft forever
vip又重新绑定在redis_master主上

测试现在redis主从是否同步数据,和之前的数据是否存在;

redis_master
[root@redis_master ~]# redis-cli 
127.0.0.1:6379> set last 111
OK
127.0.0.1:6379> get last
"111"
127.0.0.1:6379> get 1010
"1010"
127.0.0.1:6379> get 2020
"2020"
127.0.0.1:6379> get 11
"22"
127.0.0.1:6379> get 22
"33"
127.0.0.1:6379> get 33
"44"
redis_slave
[root@redis_slave ~]# redis-cli 
127.0.0.1:6379> get last
"111"
127.0.0.1:6379> get 11
"22"
127.0.0.1:6379> get 22
"33"
127.0.0.1:6379> get 123
"123"
127.0.0.1:6379> get 1010
"1010"
127.0.0.1:6379> get 2020
"2020"
127.0.0.1:6379>

数据不会丢失,全部都同步上。

redis+keepalived 主主模型,其实redis现在不支持主主,只是我们可以理解为redis主主。可以很智能的自动切换,redis主从。主要2台redis不同时挂掉,就不会丢失数据及对数据造成影响。

此方案,已经在线上使用,大家可以参考下文档。

原创文章,作者:Net20_赤羽,如若转载,请注明出处:http://www.178linux.com/19183

(3)
Net20_赤羽Net20_赤羽
上一篇 2016-06-23
下一篇 2016-06-23

相关推荐