1、redis高并发

主从架构,一主多从,一般来说,很多项目其实就足够了,单主用来写入数据,单机几万QPS,多从用来查询数据,多个从实例可以提供每秒10万的QPS。

redis高并发的同时,还需要容纳大量的数据:一主多从,每个实例都容纳了完整的数据,比如redis主就10G的内存量,其实你就最多只能容纳10g的数据量。如果你的缓存要容纳的数据量很大,达到了几十g,甚至几百g,或者是几t,那你就需要redis集群,而且用redis集群之后,可以提供可能每秒几十万的读写并发。

2、redis性能测试演示:

2.1、语法

[root@elasticsearch-04 ~]# redis-benchmark [option] [option value]
 -h : 指定服务器主机名127.0.0.1
 -p : 指定服务器端口6379
 -s : 指定服务器 socket
 -c : 指定并发连接数50# 常用
 -n : 指定请求数10000# 常用
 -d : 以字节的形式指定 SET/GET 值的数据大小2# 常用
 -k : 1=keep alive 0=reconnect1
 -r : SET/GET/INCR 使用随机 key, SADD 使用随机值
 -P : 通过管道传输 <numreq> 请求1
 -q : 强制退出 redis。仅显示 query/sec 值
 --csv : 以 CSV 格式输出
 -l : 生成循环,永久执行测试
 -t : 仅运行以逗号分隔的测试命令列表。
 -I : Idle 模式。仅打开 N 个 idle 连接并等待。

2.2、使用多个参数来测试 redis 性能

[root@elasticsearch-04 ~]# redis-benchmark -h 172.17.120.20 -p 6301 -a rds6301_paswd -c 1000 -n 10000 -d 2 -q
 PING_INLINE: 23474.18 requests per second
 PING_BULK: 29154.52 requests per second
 SET: 32786.88 requests per second
 GET: 27932.96 requests per second
 INCR: 29761.90 requests per second
 LPUSH: 43859.65 requests per second
 RPUSH: 37735.85 requests per second
 LPOP: 34482.76 requests per second
 RPOP: 38314.18 requests per second
 SADD: 37593.98 requests per second
 HSET: 26737.97 requests per second
 SPOP: 29498.53 requests per second
 LPUSH (needed to benchmark LRANGE): 36363.64 requests per second
 LRANGE_100 (first 100elements): 27173.91 requests per second
 LRANGE_300 (first 300elements): 13071.90 requests per second
 LRANGE_500 (first 450elements): 9285.05 requests per second
 LRANGE_600 (first 600elements): 8467.40 requests per second
 MSET (10 keys): 19493.18 requests per second

3、redis高可用

如果你做主从架构部署,其实就是加上哨兵就可以了,就可以实现,任何一个实例宕机,自动会进行主备切换。

图解redis replication基本原理:

服务器重启后redis数据还在怎么回事 redis重启数据恢复_数据

redis replication的核心机制(说白了就是复制)

(1)redis采用异步方式复制数据到slave节点,不过redis 2.8开始,slave node会周期性地确认自己每次复制的数据量。

(2)一个master node是可以配置多个slave node的。

(3)slave node也可以连接其他的slave node。

(4)slave node做复制的时候,是不会block master node的正常工作的。

(5)slave node在做复制的时候,也不会block对自己的查询操作,它会用旧的数据集来提供服务; 但是复制完成的时候,需要删除旧数据集,加载新数据集,这个时候就会暂停对外服务了(在毫秒到秒之间)。

(6)slave node主要用来进行横向扩容,做读写分离,扩容的slave node可以提高读的吞吐量。

4、redis持久化的引入

比如你redis整个挂了,然后redis就不可用了,你要做的事情是让redis变得可用,尽快变得可用。

重启redis,尽快让它对外提供服务,但是就像上一讲说,如果你没做数据备份,这个时候redis启动了,也不可用啊,数据都没了。

很可能说,大量的请求过来,缓存全部无法命中,在redis里根本找不到数据,这个时候就死定了,缓存雪崩问题,所有请求,没有在redis命中,就会去mysql数据库这种数据源头中去找,一下子mysql承接高并发,然后就挂了,mysql挂掉,你都没法去找数据恢复到redis里面去,redis的数据从哪儿来?从mysql来。。。

具体的完整的缓存雪崩的场景,还有企业级的解决方案,到后面讲。如果你把redis的持久化做好,备份和恢复方案做到企业级的程度,那么即使你的redis故障了,也可以通过备份数据,快速恢复,一旦恢复立即对外提供服务。比如你部署了一个redis,作为cache缓存,当然也可以保存一些较为重要的数据,如果没有持久化的话,redis遇到灾难性故障的时候,就会丢失所有的数据。如果通过持久化将数据搞一份儿在磁盘上去,然后定期比如说同步和备份到一些云存储服务上去,那么就可以保证数据不丢失全部,还是可以恢复一部分数据回来的。

综上所述:redis的持久化,跟高可用是有关系的。

5、redis持久化:RDB,AOF

1、RDB和AOF两种持久化机制的介绍

RDB持久化机制,对redis中的数据执行周期性的持久化。

AOF机制对每条写入命令作为日志,以append-only的模式写入一个日志文件中,在redis重启的时候,可以通过回放AOF日志中的写入指令来重新构建整个数据集。

如果我们想要redis仅仅作为纯内存的缓存来用,那么可以禁止RDB和AOF所有的持久化机制。

通过RDB或AOF,都可以将redis内存中的数据给持久化到磁盘上面来,然后可以将这些数据备份到别的地方去,比如说阿里云,云服务。

如果redis挂了,服务器上的内存和磁盘上的数据都丢了,可以从云服务上拷贝回来之前的数据,放到指定的目录中,然后重新启动redis,redis就会自动根据持久化数据文件中的数据,去恢复内存中的数据,继续对外提供服务。

如果同时使用RDB和AOF两种持久化机制,那么在redis重启的时候,会使用AOF来重新构建数据,因为AOF中的数据更加完整。

2、RDB持久化机制的优点

(1)RDB会生成多个数据文件,每个数据文件都代表了某一个时刻中redis的数据,这种多个数据文件的方式,非常适合做冷备,可以将这种完整的数据文件发送到一些远程的安全存储上去,比如说Amazon的S3云服务上去,在国内可以是阿里云的ODPS分布式存储上,以预定好的备份策略来定期备份redis中的数据。

(2)RDB对redis对外提供的读写服务,影响非常小,可以让redis保持高性能,因为redis主进程只需要fork一个子进程,让子进程执行磁盘IO操作来进行RDB持久化即可。

(3)相对于AOF持久化机制来说,直接基于RDB数据文件来重启和恢复redis进程,更加快速。

3、RDB持久化机制的缺点

(1)如果想要在redis故障时,尽可能少的丢失数据,那么RDB没有AOF好。一般来说,RDB数据快照文件,都是每隔5分钟,或者更长时间生成一次,这个时候就得接受一旦redis进程宕机,那么会丢失最近5分钟的数据。

(2)RDB每次在fork子进程来执行RDB快照数据文件生成的时候,如果数据文件特别大,可能会导致对客户端提供的服务暂停数毫秒,或者甚至数秒。

4、AOF持久化机制的优点

(1)AOF可以更好的保护数据不丢失,一般AOF会每隔1秒,通过一个后台线程执行一次fsync操作,最多丢失1秒钟的数据。

(2)AOF日志文件以append-only模式写入,所以没有任何磁盘寻址的开销,写入性能非常高,而且文件不容易破损,即使文件尾部破损,也很容易修复。

(3)AOF日志文件即使过大的时候,出现后台重写操作,也不会影响客户端的读写。因为在rewrite log的时候,会对其中的指导进行压缩,创建出一份需要恢复数据的最小日志出来。然后创建新日志文件的时候,老的日志文件还是照常写入。当新的merge后的日志文件ready的时候,再交换新老日志文件即可。

(4)AOF日志文件的命令通过非常可读的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复。比如某人不小心用flushall命令清空了所有数据,只要这个时候后台rewrite还没有发生,那么就可以立即拷贝AOF文件,将最后一条flushall命令给删了,然后再将该AOF文件放回去,就可以通过恢复机制,自动恢复所有数据。

5、AOF持久化机制的缺点

(1)对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大。

(2)AOF开启后,支持的写QPS会比RDB支持的写QPS低,因为AOF一般会配置成每秒fsync一次日志文件,当然,每秒一次fsync,性能也还是很高的。

(3)以前AOF发生过bug,就是通过AOF记录的日志,进行数据恢复的时候,没有恢复一模一样的数据出来。所以说,类似AOF这种较为复杂的基于命令日志/merge/回放的方式,比基于RDB每次持久化一份完整的数据快照文件的方式,更加脆弱一些,容易有bug。不过AOF就是为了避免rewrite过程导致的bug,因此每次rewrite并不是基于旧的指令日志进行merge的,而是基于当时内存中的数据进行指令的重新构建,这样健壮性会好很多。

6、RDB和AOF到底该如何选择

(1)不要仅仅使用RDB,因为那样会导致你丢失很多数据。

(2)也不要仅仅使用AOF,因为那样有两个问题,第一,你通过AOF做冷备,没有RDB做冷备,来的恢复速度更快; 第二,RDB每次简单粗暴生成数据快照,更加健壮,可以避免AOF这种复杂的备份和恢复机制的bug。

(3)综合使用AOF和RDB两种持久化机制,用AOF来保证数据不丢失,作为数据恢复的第一选择; 用RDB来做不同程度的冷备,在AOF文件都丢失或损坏不可用的时候,还可以使用RDB来进行快速的数据恢复。

6、master持久化对于主从架构的安全保障的意义(数据备份和快速的数据恢复)

如果采用了主从架构,那么建议必须开启master node的持久化!不建议用slave node作为master node的数据热备,因为那样的话,如果你关掉master的持久化,可能在master宕机重启的时候数据是空的,然后可能一经过复制,salve node数据也丢了。

master -> RDB和AOF都关闭了 -> 全部在内存中

master宕机,重启,是没有本地数据可以恢复的,然后就会直接认为自己IDE数据是空的,master就会将空的数据集同步到slave上去,所有slave的数据全部清空,100%的数据丢失。

master节点,必须要使用持久化机制。

7、master的各种备份方案,要不要做

万一说本地的所有文件丢失了; 从备份中挑选一份rdb去恢复master; 这样才能确保master启动的时候,是有数据的,即使采用了后续讲解的高可用机制,slave node可以自动接管master node,但是也可能sentinal还没有检测到master failure,master node就自动重启了,还是可能导致上面的所有slave node数据清空故障。

8、redis持久化演示:

8.1、生产环境中Redis启动前的配置

生产环境中,要把redis作为一个系统的daemon进程去运行的,每次系统启动,redis进程一起启动。

8.2、修改redis.conf中的部分配置为生产环境

daemonize   yes                            让redis以daemon进程进行
 pidfile     /var/run/redis_6379.pid         设置redis的pid文件位置
 port        6379                          设置redis的监听端口号
 dir         /var/redis/                     设置持久化文件的存储位置

8.3、修改权限

[root@elasticsearch-04 redis]# chown -R redis:redis /var/run/
 [root@elasticsearch-04 redis]# chown -R redis:redis /var/redis/

8.4、启动redis

[root@elasticsearch-04 ~]# systemctl restart redis.service

8.5、生产环境中Redis持久化配置

在生产环境中,为了保证Redis中数据的安全性,都要同时开启RDB持久化和AOF持久化。RDB进行数据冷备,AOF做数据热备。

8.6、配置RDB持久化机制

在redis.conf文件,也就是我们这里的/etc/redis.conf去配置RDB持久化

#   save ""
 save 9001

每隔60s,如果有超过1000个key发生了变更,那么就生成一个新的dump.rdb文件,就是当前redis内存中完整的数据快照,这个操作也被称之为snapshotting,快照也可以手动调用save或者bgsave命令,同步或异步执行rdb快照生成。

save可以设置多个,就是多个snapshotting检查点,每到一个检查点,就会去check一下,是否有指定的key数量发生了变更,如果有,就生成一个新的dump.rdb文件。如下配置:

save 9001
 save 30010
 save 6010000

8.7、配置AOF持久化机制

在redis.conf文件,也就是我们这里的/etc/redis.conf去配置AOF持久化

  • AOF持久化,默认是关闭的,默认打开RDB持久化
# 可以打开AOF持久化机制
 appendonly yes

打开AOF持久化机制之后,redis每次接收到一条写命令,就会写入日志文件中,当然是先写比如os cache的,然后每隔一定时间在fsync一下,可以配置AOF的fsync策略,有三种:always,everysec,no。我们通常都是用everysec。

# appendfsync always
 appendfsync everysec
 # appendfsync no

配置AOF持久化文件rewrite的配置:

auto-aof-rewrite-percentage 100 # 就是当前AOF大小膨胀到超过上次100%,上次的两倍
 auto-aof-rewrite-min-size 64mb   # 根据你的数据量来定,16mb,32mb

而且机制AOF和RDB都开启了,redis重启的时候,也是优先通过AOF进行数据恢复的,因为AOF的比较完整。

开启客户端要确保服务端启动

# 如果报错修改配置文件
 [root@elasticsearch-04 ~]# vim /etc/redis.conf 
 stop-writes-on-bgsave-error yes
 [root@elasticsearch-04 ~]# redis-server /etc/redis.conf 
 [root@elasticsearch-04 ~]# redis-cli

9、企业级的数据备份方案

RDB非常适合做冷备份,每次生成之后,就不会再有修改了。使用定时脚本执行备份方案,crontab -e,该命令详情及使用方法请看百度百科。

9.1、数据备份方案

1.写crontab定时调度脚本去做数据备份。2.每小时都copy一份rdb的备份,到一个目录中去,仅仅保留最近48小时的备份。3.每天都保留一份当日的rdb的备份,到一个目录中去,仅仅保留最近1个月的备份。4.每次copy备份的时候,都把太旧的备份给删了。5.每天晚上将当前服务器上所有的数据备份,发送一份到远程的云服务上去

9.2、每小时copy一次备份,删除48小时前的数据

执行命令:crontab -e

0* * * * sh/usr/local/redis/copy/redis_rdb_copy_hourly.sh

redis_rdb_copy_hourly.sh

[root@elasticsearch-04 2020040715]# cat /usr/local/redis/copy/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
 cp/var/redis/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

9.3、每天copy一次备份,删除一天前的备份

执行命令:crontab -e

00* * * sh/usr/local/redis/copy/redis_rdb_copy_daily.sh

redis_rdb_copy_daily.sh

[root@elasticsearch-04 2020040715]# cat /usr/local/redis/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
 cp/var/redis/dump.rdb /usr/local/redis/snapshotting/$cur_date
 
 del_date=`date -d -1month +%Y%m%d`
 rm-rf/usr/local/redis/snapshotting/$del_date

10、数据恢复方案

如果是redis进程挂掉,那么重启redis进程即可,直接基于AOF日志文件恢复数据,最多就丢一秒的数据量。如果是redis进程所在机器挂掉,那么重启机器后,尝试重启redis进程,尝试直接基于AOF日志文件进行数据恢复AOF没有破损,也是可以直接基于AOF恢复的。AOF append-only,顺序写入,如果AOF文件破损,那么用redis-check-aof fix修复,但是要注意的是,修复会导致错误的那条语句被删除,进而导致数据丢失。

我们删除aof文件一行数据并进行修复

[root@elasticsearch-04 ~]# redis-cli
 127.0.0.1:6379> settest 268900
 OK
 127.0.0.1:6379> gettest
 "268900"
 # 要等几秒才能写入aof文件里面
 [root@elasticsearch-04 redis]# cd /var/redis/
 [root@elasticsearch-04 redis]# ls
 appendonly.aof dump.rdb
 #删除一行
 [root@elasticsearch-04 redis]# vim appendonly.aof 
 #修复(删除的这一条会丢失)
 [root@elasticsearch-04 redis]# redis-check-aof --fix appendonly.aof 
 0x              71: Expected to read 5bytes, got 0bytes
 AOF analyzed: size=113, ok_up_to=86, diff=27
 This will shrink the AOF from 113bytes, with 27bytes, to 86bytes
 Continue? [y/N]: y
 Successfully truncated AOF

如果redis当前最新的AOF和RDB文件出现了丢失/损坏,那么可以尝试基于该机器上当前的某个最新的RDB数据副本进行数据恢复。当前最新的AOF和RDB文件都出现了丢失/损坏到无法恢复,一般不是机器的故障,找到RDB最新的一份备份,小时级的备份可以了,小时级的肯定是最新的,copy到redis里面去,就可以恢复到某一个小时的数据。

[root@elasticsearch-04 redis]# scp -r dump.rdb root@172.17.120.20:/var/redis/
 root@172.17.120.20's password: 
 dump.rdb                                      100%  186    1.1KB/s   00:00
 # 在172.17.120.20上执行:
 [root@redis-120-20 redis]# systemctl restart redis.service
 [root@redis-120-20 redis]# redis-cli 
 127.0.0.1:6379> gethaha
 "248"
 127.0.0.1:6379> gettest
 "268900"