4.1 单机Redis
4.1.1 Redis安装
进入docker容器
docker run -p 80:80 -itd --net shadownet --ip 172.10.89.3 --name web --hostname nginx -v E:/FangCloudSync:/data openresty-php7
docker start 0ef6
docker attach 0ef6
下载redis
在windows下载并解压,从容器进入redis安装包上级目录
cd /data/soft/
mkdir -p /usr/local/webserver/redis/
mv redis-4.0.2/* /usr/local/webserver/redis/
安装前置软件tcl
yum install tcl
安装完成后在redis目录直接make && make install安装redis
redis相关命令会被自动安装到/usr/local/bin目录内
4.1.2 Redis生产环境启动方案
- 如果是一般的学习,就随便使用redis-server启动一下redis,做一些实验,没什么意义,但生产环境需要把Redis作为一个系统的daemon进程去运行的,每次系统启动,Redis一起启动
- 1>. cp 安装包目录下utils/redis-init-script /etc/init.d/redis_6379
- 2>.修改redis_6379脚本的第6行的REDISPORT,设置为相同的端口号(默认就是6379),及修改配置文件路径为/etc/redis/redis_6379.conf
- 3>.创建目录:/etc/redis 及 /data/Work/redis/6379
- 4>.修改redis配置文件(默认在安装包根目录下,redis.conf),拷贝到/etc/redis目录中
- 5>.修改redis中的部分配置为生产环境
daemonize yes 让redis以daemon进程运行
pidfile /var/run/redis_6379.pid 设置redis的pid文件
port 6379 设置redis的监听端口号
dir /data/Work/redis/6379 设置持久化文件的存储位置
- 6>.启动redis,执行/etc/init.d/redis_6379脚本
- 7>.让redis跟随系统自启动 /etc/rc.local加入/etc/init.d/redis_6379 start
4.1.3 Redis-cli使用
- redis-cli SHUTDOWN 杀掉redis服务
- redis-cli -h 127.0.0.1 -p 6379
4.2 Redis持久化和恢复
4.2.1 Redis持久化
- redis持久化的意义在于故障恢复
- 比如你部署了一个redis,作为redis缓存,保存了一些较为重要的数据,redis如果单单把数据放在内存中,是没有任何办法应对一些灾难性的故障的
- Redis持久化机制RDB和AOF对比
- RDB:
- RDB对redis中的数据执行周期性的持久化
- 优点:
1.RDB会生成多个数据文件,每个数据文件都代表了某一时刻中redis的数据,这种多个数据文件的方式,非常适合做冷备,可以将这种完整的数据文件发送到一些远程的安全存储服务上去
RDB也可以做冷备,生成多个文件,每个文件都代表了某一时刻的完整数据快照
AOF也可以做冷备,只有一个文件,但是你可以每隔一定时间,去copy一份这个文件出来
RDB做冷备,优势在哪儿呢?由redis去控制固定时长生成快照文件的事情,比较方便;AOF还需要自己写一些脚本去做这个事情,各种定时
RDB数据做冷备,在最坏的情况下,提供数据恢复的时候,速度比AOF快
2.RDB对redis对外提供的读写服务,影响非常小,可以让redis保持高性能,因为redis主进程只需fork一个子进程,让子进程执行磁盘IO操作来进行RDB持久化即可
RDB,每次写,都是直接写redis内存,只是在一定的时候,才会将数据写入磁盘
AOF,每次都是要写文件的,虽然可以快速写个os cacahe中,但是还是有一定的时间开销,速度肯定比RDB略慢一些
3.相对于AOF持久化机制来说,直接基于RDB数据文件来重启和恢复redis进程,更加快速
AOF,存放的指令日志,做数据恢复的时候,其实是要回放和执行所有的指令日志,来恢复内存中所有的数据的
RDB,就是一份数据文件,恢复的时候,直接加载到内存中即可
综合上述优化,RDB特别适合做冷 备份
- 缺点:
1.如果想要在redis故障时,尽可能少的丢失数据,那么RDB没有AOF好,一般来说,RDB数据快照文件,都是每隔5分钟,或者更长时间生成一次,这个时候就得接受一旦redis进程宕机,那么会丢失最近5分钟的数据
这个问题,也是RDB最大的缺点,就是不适合做第一优先方案的备份
2.RDB每次在fork子进程来执行RDB快照数据一成的时候,如果数据文件特别大,可能会导致对客户端提供的服务暂停数毫秒,或者数秒
一般不要让RDB的间隔太长,否则每次生成的RDB文件太大了,对redis本身有一定的性能影响
- AOF:
- AOF对每条写入命令作为日志,以append-only的模式写入一个日志文件中,在redis重启的时候,可以通过回放AOF日志中的写入指令来重新构建整个数据集,当日志文件达到一定大小时,AOF将以当前redis中的数据做一次重写,如果同时使用RDB和AOF两种机制,则Redis重启时优先用AOF进行恢复,因为AOF中的数据更完整
- 优点:
1.AOF可以更好的保护数据不丢失,一般AOF会每隔1秒,通过一个后台线程执行一次fsync操作,最多丢失1秒钟的数据
每隔1秒,就执行一次fsync操作,保证os cache中的数据写入磁盘中
redis进程挂 了,最多丢掉1秒钟的数据
2.AOF日志文件以append-only模式写入,所以没有任何磁盘寻址的开销,写入性能非常高,而且文件不容易破损,即使文件尾部破损,也是很容易修复
3.AOF日志文件即使过大的时候,出现后台重写操作,也不会影响客户端的读写,因为rewrite log的时候,会对其中的指导进行压缩,创建出一份需要恢复数据的最小日志出来,再创建新日志文件
4.AOF日志文件的命令通过非常可读的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复。比如某人不小心用flushall命令清空了所有 数据,只要这个时候后台rewrite还没有发生,那么就可以立即拷贝AOF文件,将最后一条flushall命令给删了,然后再将该AOF文件放回去,就可以通过恢复机器,自动恢复所有数据
- 缺点:
1.对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大
2.AOF开启后,支持的QPS会比RDB支持的QPS低,因为AOF一般会配置成每秒fsync一次日志文件,当然每秒一次fsync,性能也还是很高的
3.以前AOF发生过bug,就是通过AOF记录的日志,进行数据恢复的时候,没有恢复一模一样的数据出来,所以说,类似AOF这种较为复杂的基于命令日志/merge/回放的方式,比基于RDB每次持久化一份完整的数据快照文件的方式,更加脆弱一些,容易有bug,不地AOF就是为了避免rewrite过程导致的bug,因此每次rewite并不是基于旧的指令日志进行merge的,而是基于当时内存中的数据进行指定的重新构建,这样健壮性会好很多
- 如果我们想要redis仅仅作为纯内存的缓存来用,那么可以禁止RDB和AOF所有的持久化机制
- RDB和AOF到底该如何选择?
1.不要仅仅使用RDB,因为那样会导致你丢失很多数据
2.也不要仅仅使用AOF,因为那样有两个问题,第一,你通过AOF做冷备,没有RDB做冷备来的恢复速度更快,第二,RDB每次简单粗暴生成数据快照,更加健壮,可以避免AOF这种复杂的备份和恢复机制的bug
3.综合使用AOF和RDB两种持久化机制,用AOF来保证数据不丢失,作为数据恢复的第一选择;用RDB来做不同程度的冷备,在AOF文件中都丢失或损坏不可以用时候,还可以使用RDB来进行快速的数据恢复
4.2.2 Redis的RDB持久化配置以及数据恢复实验
- 1.如何配置RDB持久化机制
- 也就是/etc/redis/redis_6379.conf里配置
save 60 1000 #每隔60秒,如果有1000个key发生了变更,那么就生成一个新的dump.rdb文件,就是当前redis内存中完整的数据快速,也可以手动调用save或者bgsave命令,同步或异步执行rdb快照生成
save可以设置多个,就是多个snapshotting检查点,每到一个检查点,就会去check一下,是否有指定的key数量发生了变更,如果有就生成
2.RDB持久化机制的工作流程
1>.redis根据配置自己尝试去生成rdb快照文件
2>.fork一个子进程出来
3>.子进程尝试将数据dump到rdb快照文件中
4>.完成rdb快照文件的生成之后,就替换之前旧的快照文件
3.基于RDB持久化机制的数据恢复实验
1>.在redis中保存几条数据,立即停掉redis进程,然后重启redis,看看刚才插入的数据是否还在
2>.手动设置一个save检查点,save 5 1
3>写入几条数据,等待5秒钟
4>停掉redis进程,再重新启动redis,看刚才插入的数据还在不在
4.2.3 Redis的AOF持久化深入讲解各种操作和相关实验
- 1.AOF持久化的配置
- AOF持久化,默认是关闭的
- appendonly yes,可以打开AOF持久化
- 打开AOF持久化机制后,redis每次接收到一条写命令,就会写入日志文件中,当然是先写入os cache的,然后每隔一定时间再fsync一下
- 而且即使AOF和RDB都开启了,redis重启的时候,也是优先通过AOF进行数据恢复的
- 可以配置AOF的fsync策略,有三种策略可以选择,一种是每次写入一条数据就执行一次fsync,一种是每隔一秒执行一次fsyn,一种是不主种执行fsync
always:每次写入一条数据,立即将这个数据对应的写日志fsync到磁盘上去;性能非常非常差,吞吐量很低;确保redis里的数据一条都不丢,就只能这样了
mysql->内存策略,大量磁盘,QPS[每秒钟请求数量]到多少,一两k
redis->内存,磁盘持久化,QPS到多少,单机一般上万QPS没问题
everysec:每秒将os cache中的数据fsync到磁盘,这个是最常用的,生产环境一般这么配置,性能很高,QPS还是可以上万的
no:仅仅redis负责将数据写入os cache就不管了,然后后面os自己会时不时有自己的策略将数据刷入磁盘,不可控
2.AOF持久化的数据恢复实验
1>.先仅仅打开RDB,写入一些数据,然后kill -9杀掉redis进程,接着重启redis,发现数据没了,因为RDB快照还没生成
2>.打开AOF的开关,启用AOF持久化
3>.写入一些数据,观察AOF文件中的日志内容
4>.kill -9杀掉redis进程,重新启动redis进程,发现数据被恢复回来了,就是从AOF文件中恢复回来的
3.AOF rewrite
redis中的数据是有限的,很多数据会自动过期或被用户删除,还可能会被redis用缓存清除的算法清理掉
redis中的数据会不断淘汰掉旧的,就一部分常用的数据会被自动保留在内存中
所以可能很多之前的已经被清理掉旧的数据,对应的写日志还停留在AOF中,AOF日志文件就一个,会不断的膨胀到很大很大
因而AOF会自动在后台每隔一定时间做rewrite操作,比如日志里已经存放了针对100W数据的日志文件了;redis内存只剩下10W;基于内存中当前的10W数据构建一套最新的日志到AOF去覆盖之前的老日志;确保AOF日志文件不会过大,保持跟redis内存数据量一致
redis2.4之前,还需要手动通过BGREWRITEAOF命令去执行AOF rewrite,但是redis 2.3之后,会自动进行rewrite操作
在redis.conf中,可以配置rewrite策略
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
比如上一次AOF rewrite后,是128mb,然后接着128mb继续写AOF的日志,如果发现增长的比例,超过了之前的100%,256mb,就可能会去触发一次rewrite
但是此时还要去跟min-size,64mb去比较,256mb>64mb,才会去触发rewite
1.redis fork一个子进程
2.子进程开始在一个新的临时的AOF文件中写入日志
3.主进程在内存中写入日志,同时新的日志也继续写入旧的AOF文件
4.子进程写完之后,主进程将内存中的新日志再次追加到新的AOF文件中
5.用新的日志文件替换掉旧的日志文件
4.AOF破损文件的修复
如果redis在append数据到AOF文件时,机器宕机了,可能会导致AOF文件破损
用redis-check-aof --fix命令来修复破损的AOF文件
5.AOF和RDB同时工作
1.如果RDB在执行snapshotting操作,那么redis不会执行AOF rewrite;如果redis在执行AOF rewrite,那么就不执行RDB snapshotting
2.如果RDB在执行snapshotting,此时用户执行BGREWRITEAOF命令,那么等RDB快照生成之后,才会去执行AOF rewrite
3.同时有RDB snapshotting文件和AOF日志文件,那么redis重启的时候,会优先使用AOF进行数据恢复,因为其中的日志更完整
最后一个小实验,让大家对redis的数据恢复有更加深刻的体会
1.在有rdb的dump和aof的appendonly的同时,rdb里也有部门数据,aof里也有部分数据,这个时候会发现,rdb的数据不会恢复到内存中
2.我们模拟让aof破损,然后fix,有一条数据会被fix删除
3.再次用fix得aof文件去重启redis,发现数据只剩下一条了
数据恢复完全是依赖于底层的磁盘持久化的
4.2.4 Redis企业级数据备份方案
企业级的数据备份和各种灾难下的数据恢复,是如何做到的呢?
RDB非常适合做冷备,每次生成之后,就不会再有修改了
1.企业级的持久化的配置策略
save 60 10000:如果你希望尽可能确保RDB最多丢1分钟的数据,那么尽量每隔1分钟都能生成一个快照
AOF一定要打开,fsync,everysec
auto-aof-rewrite-percentage 100:就是当前AOF大小膨胀到超过上次100%,上次的两倍
auto-aof-rewrite-min-size 64mb:根据你的数据量来定,16mb,32mb
2.企业级数据备份方案:
1.写crontab定时调度脚本去备份数据
2.每小时copy一份rdb的备份到一个目录中去,仅仅保留最近48小时的备份
3.每天保留一份当日的rdb备份到一个目录中去,仅仅保留最近1月的备份
4.每次copy备份的时候,都把太旧的备份删除
5.每天晚上将当前服务器上所有的数据备份,发送一份到远程的云服务上去
- 每小时copy一份,删除48小时内的
redis_rdb_copy_hourly.sh
#!/bin/sh
cur_date = `date +%Y%m%d%k`
rm -rf /usr/local/redis/snapshotting/$cur_date
mkdir /usr/local/redis/snapshotting/$cur_date
scp /var/redis/6379/dump.rdb /usr/local/redis/snapshotting/$cur_date
del_date=`date -d -48hour +%Y%m%d%k`
rm -rf /usr/local/redis/snapshotting/$del_date
- 每天copy一次备份
redis_rdb_copy_daily.sh
#!/bin/sh
cur_date = `date +%Y%m%d`
rm -rf /usr/local/redis/snapshotting/$cur_date
mkdir /usr/local/redis/snapshotting/$cur_date
scp /var/redis/6379/dump.rdb /usr/local/redis/snapshotting/$cur_date
del_date=`date -d -1month +%Y%m%d`
rm -rf /usr/local/redis/snapshotting/$del_date
- 每天一次将所有数据上传到远程的云服务器上去
3.数据恢复方案
1.如果是redis进程挂掉,那么重启redis进程即可,直接基于AOF日志文件恢复数据
2.如果是redis进程所在机器挂掉,那么重启机器后,尝试重启redis进程,尝试直接基于AOF文件进行数据修复
AOF没有破损,也是可以直接基于AOF恢复的
AOF append-only,顺序写入,如果AOF文件破损则用redis-check-aof fix
3.如果redis当前最新的AOF和RDB文件出现了丢失/损坏,那么可以尝试基于该机器上当前的某个最新的RDB数据副本进行数据恢复
当前最新的AOF和RDB文件都出现了丢失/损坏到无法恢复,一般不是机器的故障,人为
4.如果当前机器上的所有RDB文件全部损坏,那么从远程的云服务上拉取最新的RDB快照回来恢复数据
5.如果是发现有重大的数据错误,比如某个小时上线的程序一下子将数据全部污染了,数据全错了,那么可以选择某个更早的时间点对数据进行恢复
注意恢复顺序:停止redis,关闭aof,拷贝rdb备份,重启redis,确认数据恢复,直接在命令行热修改redis配置,打开aof,这个redis就会将内存中的数据写入aof,此时aof和rdb两份数据文件就同步了,否则空aof会覆盖rdb为空
4.3 Redis读写分离
4.3.1 Redis通过读写分离来承载请求QPS超过10W+?
Redis不能高并发的瓶颈?
单机Redis,能够承载的QPS大概在上W到几W不等
如果Redis要支撑超过10W+(并发),那应该怎么做?
单机的Redis几乎不太可能说QPS超过10W+,除非一些特殊情况,比如你的机器性能特别好,配置特别高,物理机,维护做的特别好,而且整体操作不是太复杂
读写分离,一般来说,对缓存,一般都是用来支撑读高并发的,写的请求是比较少的,可能写请求也就一秒钟,几千,一两千,大量的请求都是读,一秒钟二十万次读