redis + keepalived 雙主模型
架構圖:
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.www58058.com/19183