我们已经知道对于一个企业级的redis架构来说,持久化是不可减少的,持久化主要是做灾难恢复,数据恢复,也可以归类到高可用的一个环节里面去。比如你redis整个挂了,然后redis就不可用了,你要做的事情是让redis变得可用,尽快变得可用。
重启redis,尽快让它对外提供服务,如果你没做数据备份,这个时候redis启动了,也不可用啊,数据都没了。
很可能说,大量的请求过来,缓存全部无法命中,在redis里根本找不到数据,这个时候就死定了,缓存雪崩问题,所有请求,没有在redis命中,就会去mysql数据库这种数据源头中去找,一下子mysql承接高并发,然后就挂了。
mysql挂掉,你都没法去找数据恢复到redis里面去,redis的数据从哪儿来?大部分情况是从mysql来。
如果你把redis的持久化做好,备份和恢复方案做到企业级的程度,那么即使你的redis故障了,也可以通过备份数据,快速恢复,一旦恢复立即对外提供服务。
redis持久化:RDB,AOF
1、RDB和AOF两种持久化机制的介绍
RDB持久化机制,是对redis中的数据执行周期性的持久化,也就是每隔几分钟或者几个小时(这个阈值是可以配置的),就会生成一份redis内存当前数据完整的快照。那么有一个疑问,一直生成,那文件不是会很多,占用空间么?实际上我们可以配置删掉之前的文件,只保留新鲜的快照即可。
AOF机制,把每一条命令数据写入到os的cache中,每隔一秒(很短间隔),就会调用操作系统的fsync操作将写入数据的命令刷到AOF文件中,也就是相当于记日志,以append-only的模式写入AOF日志文件中,在redis重启的时候,可以通过回放AOF日志中的写入指令来重新构建整个数据集。AOF文件就是在磁盘上,AOF文件会越写越大,内存怎么放得下呢,所以需要解决这个问题。当文件大到一定程度的时候,redis就会生成一个新的AOF文件,然后将旧的文件给删除了,也就是AOF的rewrite操作。(AOF只会记录写命令(也就是对数据有所修改),读命令对内存数据没有影响,所以不会记录)。
rewrite操作也就是根据当时redis内存中的数据构造一个更小的文件。这句话怎么理解?redis不仅有增加,修改,还有删除,这些命令都对数据有所修改,这些操作都会记录下来就会很大,但是我们如果知道内存中的数据,将内存中所有的数据都当成新增的,来构造日志,相信会小很多。
比如:redis中有一百万数据,已经满了,这些数据的写操作都被记录到AOF中,那么AOF文件中就会有100万数据的写入操作记录,这个时候要是再来50万数据,已经超出了内存的限制,就会使用LRU机制删除最久不使用的数据,所以数据还是一百万,但是AOF还是会持续写入这50万数据的修改记录,那么这个文件就会越来越大。当文件达到一定大小(这个阈值是我们设置的),基于AOF rewrite就会搞一个新的AOF文件,是当前100万数据的最小写入命令的AOF文件,然后删除之前的AOF文件。
我们都知道redis的数据是存在于内存中,内存是有限的,那么如果数据很大,越来越大,内存就放不下,这个时候redis就会采取一定措施(LRU算法,也就是淘汰很久没有使用过的数据),将一部分数据清理出去。所以维持内存的数据在一定范围。
如果我们想要redis仅仅作为纯内存的缓存来用,就算挂掉也无所谓,那么可以禁止RDB和AOF所有的持久化机制。
通过RDB或AOF,都可以将redis内存中的数据给持久化到磁盘上面来,然后可以将这些数据备份到别的地方去,比如说阿里云等云服务。如果redis挂了,服务器上的内存和磁盘上的数据都丢了,可以从云服务上拷贝回来之前的数据,放到指定的目录中,然后重新启动redis,redis就会自动根据持久化数据文件中的数据,去恢复内存中的数据,继续对外提供服务。
如果同时使用RDB和AOF两种持久化机制,那么在redis重启的时候,会优先使用AOF来重新构建数据,因为AOF中的数据更加完整。
2、RDB持久化机制的优点
(1)RDB会生成多个数据文件,每个数据文件都代表了某一个时刻中redis的数据,这种多个数据文件的方式,非常适合做冷备份,可以将这种完整的数据文件发送到一些远程的安全存储上去,比如说Amazon的云服务上去,在国内可以是阿里云的ODPS分布式存储上,以预定好的备份策略来定期备份redis中的数据。
(2)RDB对redis对外提供的读写服务,影响非常小,可以让redis保持高性能,因为redis主进程只需要fork一个子进程,让子进程执行磁盘IO操作来进行RDB持久化即可。
(3)相对于AOF持久化机制来说,直接基于RDB数据文件来重启和恢复redis进程,更加快速。因为AOF存放的是指令日志,所以数据恢复的时候需要回放每一个操作,也就是执行所有之前的过程来进行数据恢复。RDB是直接将数据加载到内存中。
3、RDB持久化机制的缺点
(1)如果想要在redis故障时,尽可能少的丢失数据,那么RDB没有AOF好。一般来说,RDB数据快照文件,都是每隔5分钟,或者更长时间生成一次,这个时候就得接受一旦redis进程宕机,那么会丢失最近5分钟的数据。RDB不适合做第一优先的恢复方案,可能数据恢复地比较多。
(2)RDB每次在fork子进程来执行RDB快照数据文件生成的时候,如果数据文件特别大,可能会导致对客户端提供的服务暂停数毫秒,或者甚至数秒。所以一般不能让RDB的间隔太长,这样每次生产的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文件放回去,就可以通过恢复机制,自动恢复所有数据。(因为AOF文件我们是可以读懂的)
5、AOF持久化机制的缺点
(1)对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大
(2)AOF开启后,支持的写QPS会比RDB支持的写QPS低,因为AOF一般会配置成每秒fsync一次日志文件,当然,每秒一次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来进行快速的数据恢复。
此文章仅代表自己(本菜鸟)学习积累记录,或者学习笔记,如有侵权,请联系作者删除。人无完人,文章也一样,文笔稚嫩,在下不才,勿喷,如果有错误之处,还望指出,感激不尽~
技术之路不在一时,山高水长,纵使缓慢,驰而不息。