公司线上一个项目数据存储采用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)步。