redis数据恢复
公司線上一個項目數據存儲采用MySQL,共分為10個庫,分布在4臺機器上,每個庫數據量約為10G,各機器均采用RAID5加速磁盤訪問;
當同時在線人數達高峰期(10w),DB磁盤IO壓力巨大,導致訪問巨慢,,在線人數就很難上不去了。
針對上面描述情況,使用redis后可有效解決這一瓶頸,因為Redis數據讀寫都是直接操作內。
解決方案:
將部分數據壓縮導入到redis后,總數據量約30G(轉換成redis數據類型數據量),一主一從模型,共兩組。
一臺機器內存32G,開10個實例,共20個實例,多實例方便做持久化。
同樣適用于上面的redis持久化策略調整方案(思路和上面一致)
主從庫配置:
主庫:關閉save開展,aof默認不打開,允許從庫訪問。主庫設置了密碼訪問requirepass My#redis
從庫:需增加配置:開啟AOF持久化,關閉save快照,設置密碼;
從庫10個實例的配置文件分別為:slave6001.conf ~ slave6010.conf
slave6001.conf配置內容如下(其他實例拷貝這個,修改端口等其他信息即可)
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | daemonize?yes pidfile?/var/run/slave6001.pid port 6001 timeout 300 loglevel debug logfile?/usr/local/redis/var/debug6001.log syslog-enabled?yes databases 16 rdbcompression?yes dbfilename slave6001.rdb dir?/data/redis-data/slave6001 slaveof 192.168.0.139 6001 masterauth My#redis slave-serve-stale-data?yes requirepass My#redis appendonly?yes appendfilename slave6001.aof appendfsync everysec no-appendfsync-on-rewrite no vm-enabled no vm-swap-file?/tmp/redis.swap vm-max-memory 0 vm-page-size 32 vm-pages 134217728 vm-max-threads 4 hash-max-zipmap-entries 512 hash-max-zipmap-value 64 list-max-ziplist-entries 512 list-max-ziplist-value 64 set-max-intset-entries 512 activerehashing?yes |
主庫每晚12點給每個實例手動做一次bgsave快照。主庫備份腳本(redis_bgsave.sh)
| 1 2 3 4 5 6 7 8 9 | #!/bin/bash #date=`date +%y%m%d_%H%M%S` REDISPASSWORD=My#redis for?PORT?in?`seq?6001 6010` do /usr/local/redis/bin/redis-cli?-h 127.0.0.1 -p $PORT -a $REDISPASSWORD bgsave sleep?10 done date?>>?/usr/local/redis/var/bgsave.log |
從庫每晚12點拷貝每個實例的AOF到其他目錄并對其打包,壓縮包要有異地備份,之后再壓縮AOF(bgrewriteaof)。
從庫備份AOF并bgrewriteaof腳本(redis_backup.sh :對單個實例)
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #!/bin/sh ## FD:File Dir ## RD:Runing Dir ## 第一個參數為redis實例名 if?[ $# -ne 1 ]; then echo?“Usage:$0? redis_name” exit fi CURDATE=`date?+%Y%m%d` CURHOUR=`date?+%Y%m%d_%H` CURTIME=`date?+%Y%m%d_%H%M%S` REDISPASSWORD=My#redis REDISNAME=$1 PORT=`echo?$REDISNAME |?cut?-c6-9` LOGFILE=/data/logs/redisbak/redis_allbak_${CURDATE}.log if?[?"${REDISNAME}"?=?""?];?then echo?“redis name Error!” exit?1 else if?[ ! -d?"/data/redis-data/${REDISNAME}"?];?then echo?“redis name Error!” exit?1 fi fi DDIR=/data/backup/redis/$CURHOUR mkdir?-p ${DDIR} RDIR=/data/redis-data/$REDISNAME cd?${RDIR} tar?-zcf $DDIR/${REDISNAME}_${CURTIME}.tar.gz $REDISNAME.aof if?[ $? != 0 ];?then echo?“tar?error $REDISNAME.aof” >> $LOGFILE #exit 1 fi sleep?5 /usr/local/redis/bin/redis-cli?-h 127.0.0.1 -p $PORT -a $REDISPASSWORD bgrewriteaof sleep?5 ###? delete old backup data dir? ### #/bin/rm -rf `date -d -7day +”%Y%m%d”` find?/data/backup/redis/?-mtime +7 |?xargs?rm?-rf echo?“Backup $REDISNAME ok at $CURTIME !” >> $LOGFILE |
從庫對所有實例備份(/data/sh/redis_allbak.sh)
| 1 2 3 4 5 6 7 | #!/bin/sh CURDATE=`date?+%Y%m%d` LOGFILE=/data/logs/redisbak/redis_allbak_${CURDATE}.log for?PORT?in?`seq?6001 6010` do /data/sh/redis_backup.sh slave${PORT} &&?echo?“slave${PORT} ok `date?+%Y%m%d_%H%M%S`” >> $LOGFILE 2>&1 ||?echo?“slave${PORT} backup error” >> $LOGFILE 2>&1 done |
操作注意事項
1)若主庫掛了,不能直接開啟主庫程序。若直接開啟主庫程序將會沖掉從庫的AOF文件,這樣將導致只能恢復到前一天晚上12的備份。
2)程序在跑時,不能重啟網絡(程序是通過網絡接口的端口進行讀寫的)。網絡中斷將導致中斷期間數據丟失。
3)確定配置文件全部正確才啟動(尤其不能有數據文件名相同),否則會沖掉原來的文件,可能造成無法恢復的損失。
災難恢復
1)主庫故障,快速恢復到最近狀態描述:主庫掛了(redis程序掛了/機器宕機了),從庫正常,恢復到主庫掛掉的時間點:去從庫手動做一次快照,拷貝快照到主庫相應目錄,啟動,OK。
在從庫做一次快照,轉移快照文件到其他目錄,將快照文件目錄拷貝到主庫相應目錄,啟動主庫,OK!
( /data/sh/redis_bgsave_cp.sh )
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #!/bin/bash REDISPASSWORD=My#redis for?PORT?in?`seq?6001 6010` do /usr/local/redis/bin/redis-cli?-h 127.0.0.1 -p $PORT -a $REDISPASSWORD bgsave sleep?5 done sleep?15 for?PORT?in?`seq?6001 6010` do SDIR=/data/redis-data/slave${PORT}/ DDIR=/data/redis_recovery/redis-data/ mkdir?-p $DDIR/redis${PORT}/ cd?$SDIR cp?-rf slave${PORT}.rdb $DDIR/redis${PORT}/redis${PORT}.rdb #sleep 1 done |
在主庫將原來數據目錄重命名。
從從庫拷貝快照文件到主庫。
啟動主庫。
2)恢復到當天12點狀態注意備份數據(當前狀態AOF+正常退出快照)!
停止redis。
解壓AOF(/data/sh/redis_untar.sh)
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #!/bin/bash DAY=20111102 SDIR=/data/backup/redis/20161102_00/ cd?$SDIR for?PORT?in?`seq?6001 6010` do tar?-zxf slave${PORT}_$DAY_*.tar.gz sleep?2 done 切割AOF(/data/sh/redis_sed.sh) #!/bin/bash DDIR=/data/redis_recovery/ TAG=”TAG111101_1200″ for?PORT?in?`seq?6001 6010` do SDIR=/data/backup/redis/20161102_00/ SAOF=${SDIR}/slave${PORT}.aof line=`sed?-n “/$TAG/=” $SAOF` num=$[$line + 3] mkdir?-p ${DDIR}/slave${PORT}/ sed?“${num},\$d” $SAOF > ${DDIR}/slave${PORT}/slave${PORT}.aof done |
將原來數據目錄重命名。
將切割出來的AOF目錄重命名為配置文件的數據目錄。(注釋主從同步配置項)。
啟動從庫。
做快照,拷貝到主庫,啟動主庫(同上面第1)步)。
3)恢復到兩天或幾天前12點狀態從庫每晚備份要備份AOF未bgrewriteaof之前的數據,可根據當天晚上12點備份,沒有bfrewriteaof之前的AOF文件來進行恢復,方法同上面的第2)步。
?
?
公司線上redis主從環境下的持久化策略調整:
描述:
之前線上項目使用redis,部署了redis主從環境。redis的主從復制功能非常強大,一個master可以擁有多個slave,而一個slave又可以擁有多個slave,如此下去,形成了強大的多級服務器集群架構。由于主redis采用了AOF和save快照的持久化,長時間下去,aof文件不斷增大,磁盤空間使用率逐漸暴增。
考慮到性能問題,需要對redis持久化做些調整,調整如下:
? ?1)主庫不開啟AOF持久化,并關閉save快照功能(即注釋默認的三個save設置),只在每晚12點定時手動做一次bgsave快照,并將快照文件轉移到異地。即主庫上不產生appendonly.aof持久化文件,做的快照數據放在.rdb文件里(如dump.rdb,由于是壓縮配置(rdbcompression yes表示快照文件要壓縮),所以快照文件要比aof文件小),然后將這個快照文件dump.rdb轉移到其他的服務器上,防止主服務器宕機造成的損失!
? ?2)從庫開啟AOF持久化并1秒落地,同樣不做快照save。并在每晚12點做一次bgrewriteaof壓縮appendonly.aof持久化文件,壓縮前先對aof文件進行備份。
--------------------------------------------------------------------------------------------------------------------------------------------
按照這種方法進行redis持久化調整,由于線上redis的主庫之前采用了AOF和save快照的持久化,之后將這兩種都關閉,從庫采用AOF持久化。出現了下面的現象:
就是主庫關閉AOF和save快照后,主redis上的appendonly.aof持久化文件在一段時間內還在刷,在增大,這是正常的,由于之前開啟的緣故,刷過一段時間,主redis的appendonly.aof持久化文件就不刷了,只有從redis的appendonly.aof持久化文件在刷了
--------------------------------------------------------------------------------------------------------------------------------------------
主從redis部署的主要目的:數據持久化,災難恢復,冗余。主庫不落地,減少消耗。
1)主庫不做AOF,不做快照,允許從庫訪問即可。
2)從庫開啟AOF,不做save
3)備份策略:
主庫每晚12點整給每個實例手動做一次bgsave快照,并將快照文件備份到遠程節點上。
從庫每晚12點整對AOF文件打包備份(tar),打包備份后做一次AOF文件壓縮(bgrewriteaof)。每天的數據起始點是前一天晚上rewriteaof后的數據。
主庫服務器腳本:
即主庫快照之后,將快照文件轉移到異地即從庫機器192.168.1.121/135上面。
| 1 2 3 4 5 6 7 8 9 | [root@192-168-1-132 redis]# cat redis_bgsave.sh #!/bin/bash CURHOUR=`date?+%Y%m%d_%H` /usr/local/bin/redis-cli?-h 127.0.0.1 -p 6379 bgsave sleep?10 rsync?-av?/data/redis/dump.rdb root@192.168.1.121:/data/backup/192.168.1.132-save/$CURHOUR/ rsync?-av?/data/redis/dump.rdb root@192.168.1.135:/data/backup/192.168.1.132-save/$CURHOUR/ sleep?10 date?>>?/data/logs/bgsave.log |
從庫服務器腳本:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | [root@cdn redis]# cat redis_backup.sh #!/bin/bash ? CURDATE=`date?+%Y%m%d` CURHOUR=`date?+%Y%m%d_%H` CURTIME=`date?+%Y%m%d_%H%M%S` LOGFILE=/data/logs/redisbak/redis_allbak_${CURDATE}.log REDISNAME=appendonly.7000 DDIR=/data/backup/redis/$CURHOUR mkdir?-p ${DDIR} RDIR=/data/redis cd?${RDIR} tar?-zcf $DDIR/${REDISNAME}_${CURTIME}.tar.gz appendonly.7000.aof if?[ $? != 0 ];?then ??echo?"tar error $REDISNAME.aof"?>> $LOGFILE fi sleep?5 /usr/local/bin/redis-cli?-h 127.0.0.1 -p 6379 bgrewriteaof sleep?5 ? ###? delete old backup data dir? ### #/bin/rm -rf `date -d -30day + "%Y%m%d"` find?/data/backup/redis/?-mtime +30 |?xargs?rm?-rf echo?"Backup $REDISNAME ok at $CURTIME !"?>> $LOGFILE |
[root@cdn redis]# crontab -e
59 23 * * * /bin/bash /data/redis/redis_backup.sh >/dev/null 2>&1
[root@cdn redis]# cd /data/backup/redis/20161207_13
[root@cdn 20161207_13]# ls
appendonly.7000_20161207_133131.tar.gz
總結
- 上一篇: JDK源码解析之 Java.lang.E
- 下一篇: 创造型模式——单例模式