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

相关推荐

  • 用NFS搭建wordpress让两台httpd服务同时服务

    一、博客实践作业: (1) nfs server导出/data/application/web,在目录中提供wordpress;  (2) nfs client挂载nfs server导出的文件系统至/var/www/html; (3) 客户端(lamp)部署wordpress,并让其正常访问;要确保能正常发文章,上传图片; (4) 客户端2(la…

    2017-06-07
  • 部署LAMP之WordPress, PMA(https), Discuz

    一、环境介绍     系统:CentOS 6.7     软件:httpd-2.2, mysql-5.3, wordpress-4.3, pma4.0     网络:       …

    Linux干货 2016-03-24
  • 任务计划管理

    一:单一工作调度:at命令       列出在指定的时间和日期在计算机上运行的已计划命令或计划命令和程序。必须正在运行“计划”服务才能使用 at 命令。 示例: [root@CentOS 6 ~]#/etc/init.d/atd restart   启动服务 …

    Linux干货 2016-09-12
  • 在VMware Workstation上安装CentOS 7

    1.新建虚拟机设备设置 2.开启此虚拟机,进行安装设置    需设置4处  时间,SOFTWARE SELECTION,分区,NETWORK & HOST NAME    (1) 首先 时间设置,选中上海时间,设置现在的Windows时间,设置好后,点击Done退出。(下面同意Done保存退…

    2017-07-15
  • debian8下安装配置部署zabbix3.0

    一、安装配置zabbix server     web server服务器:172.28.0.187     mysql服务器:172.28.0.237     1、安装web server(172.28.0.187)  &nbs…

    Linux干货 2016-05-07
  • vim文件编辑器

       vi命令是UNIX操作系统和类UNIX操作系统中最通用的全屏幕纯文本编辑器。Linux中的vi编辑器叫vim,它是vi的增强版(vi Improved),与vi编辑器完全兼容,而且实现了很多增强功能。 vim功能十分强大,具有很多有优点: 所有的unix like系统都会内置vi文本编辑器,其他的文本编辑器则不一定会有 很多软件的编…

    Linux干货 2016-08-11