前言Cache以其高并发、高性能的特点,在项目中得到了广泛的应用。读持久化、数据备份、数据故障恢复,你了解多少?一、redis持久化的意义——redis故障恢复在实际生产环境中,redis很可能会突然挂掉,比如redis进程挂掉,电缆被施工队挖了(支付宝的例子)等。总之,会出现各种奇怪的现象导致redis死掉。这时候redis内存中的数据就会全部丢失。这些数据可能服务于许多系统或服务。当然我们可以重启redis。重启后,如果不持久化redis,redis中的所有数据都会丢失。如果通过持久化的方式将数据复制到磁盘,然后定期同步备份到云存储服务,可以保证所有数据不会丢失,部分数据还是可以恢复的。2、两种持久化机制(RDB和AOF)RDB:对redis数据进行周期性持久化AOF:将每条命令写入日志,以append-only方式写入日志文件,在redis中重启使用AOF时,可以通过回放AOF写命令重建整个数据集。是否实用耐用取决于具体的业务场景:如果只是想让redis作为纯内存缓存使用,可以禁用RDB和AOF。故障恢复的大致思路:通过RDB或者AOF,将redis内存中的数据持久化到磁盘,然后再将数据备份到阿里云。如果redis挂了,服务器内存和磁盘中的数据都会丢失。这时可以将阿里云中的备份文件复制到指定目录,然后重启redis,redis会根据持久化数据文件自动恢复内存中的数据,继续对外提供服务。如果室友同时拥有RDB和AOF持久化机制,建议在重启时使用AOF重建数据,因为AOF中的数据更完整。3、分析RDB和AOFRDB:早上7点,此时redis中有500条数据。这时候redis会在一定时间内生成一个RDB快照文件。9点的时候,redis中有8000条数据。另一个RDB快照文件在一定时间内生成,这就是RDB持久化机制。AOF:redis每写入一条指令,该指令就会更新到磁盘上的文件中。但是在现代操作系统中,写入文件并不是直接写入磁盘,而是先写入os缓存,然后在一定时间内从os缓存中刷入磁盘文件。对于AOF,每秒调用一次操作(可配置)系统的fsync操作强制将os缓存中的数据刷新到磁盘文件中。但是,redis内存中的数据并不是持续增长的。它根据LRU算法定时清理一些不常用的数据,保证AOF不会不断增长。但是,如果LRU的清理速度没有AOF扩展速度快,此时,当AOF足够大到一定程度时,就会进行AOF重写操作。AOF重写操作会根据当时redis内存中的数据重构一个更小的AOF文件,然后删除旧的AOF文件。简单的说,假设redis被限制只能存储10G的数据,此时,数据不断的往redis中写入。当数据量达到10G时,这时候按照LRU清理一些不经常使用的数据,5G数据清理,这时候又写了5G。此时AOF文件记录了15G数据相关的写指令。如果此时AOF已经扩容,redis会在此时进行AOF重写操作,重新生成一条新的10G数据指令。AOF文件,此时会继续写入新的AOF文件,删除旧的AOF文件。4.RDB和AOF的优缺点RDB的优点(1)。RDB会生成多个数据文件,每个数据文件代表redis在某个时刻的数据。这种多数据文件的方式非常适合冷备份,可以将这个完整的数据文件发送到一些远程的安全存储,比如阿里云的ODPS分布式存储,使用预定的备份策略定期备份redis中的数据。RDB做冷备份,生成多个文件。每个文件代表某个时刻的完整数据快照。AOF也可以用于冷备份。只有一个文件,但您可以定期复制此文件。但是RDB更适合做冷备份。它的好处是redis可以控制定时生成快照文件,比较方便;AOF,需要写一些脚本来做这个,需要自己写定时脚本,和RDB数据做冷备份,最坏情况下,在提供数据恢复的时候,速度比AOF快(2)。RDB对redis提供的读写服务影响很小,可以保持redis的高性能,因为redis的主进程只需要fork一个子进程,让子进程进行磁盘IO操作来持久化RDB。RDB,每次写入,都是直接写入redis内存,只有在一定的时候,才会将数据写入到磁盘上的AOF中。每次都要写文件。虽然可以快速写入os缓存,但是还是有一定的时间开销,速度肯定比RDB(3)略慢。与AOF持久化机制相比,它直接基于RDB数据文件来重启和恢复redis进程,速度更快。RDB的缺点(一)。如果想在redis失效的时候尽可能少的丢失数据,那么RDB不如AOF。一般来说,RDB数据快照文件每5分钟或更长时间生成一次。这时候你就不得不接受,一旦redis进程宕机,最后5分钟的数据就会丢失。这也是RDB***的缺点,就是不适合优先级最高的恢复计划。如果依赖RDB作为优先级最高的恢复方案,会造成更多的数据丢失。(2).RDB每次在fork子进程中执行RDB快照数据文件生成,如果数据文件特别大,可能会导致客户端提供的服务暂停几毫秒,甚至几秒,所以一般不要让RDB间隔时间过长,否则每次生成的rdb文件过大,可能会影响redis本身的性能。AOF的优点(1)。AOF可以更好的保护数据不丢失。一般AOF每隔1秒就会通过一次。后台线程执行fsync操作,最多丢失1秒数据。每隔1秒执行一次fsync操作,确保os缓存中的数据写入磁盘。如果redis进程挂了,最多丢失1秒的数据。.(2).AOF日志文件采用append-only方式写入,因此没有磁盘寻址开销,写入性能非常高,文件不易损坏。即使文件末尾损坏,也很容易修复。(3).即使AOF日志文件过大,后台rewrite操作也不会影响客户端的读写。因为在重写日志的时候,内容会被压缩,创建一个需要恢复数据的最小日志。创建新日志文件时,旧日志文件仍照常写入。当新的合并日志文件准备就绪时,只需交换旧日志文件和新日志文件即可。(4).AOF日志文件的命令以可读的方式记录。这个特性非常适合灾难性误删的紧急恢复。例如,有人不小心用flushall命令清除了所有数据。只要此时后台rewrite还没有发生,就可以马上复制AOF文件,删除最后的flushall命令,放回AOF文件。可以通过AOF恢复机制自动恢复所有数据缺点(一)。同一份数据,AOF日志文件通常比RDB数据快照文件大(2)。开启AOF后,支持的写QPS会比RDB支持的写QPS低,因为AOF一般配置为每秒fsync日志文件一次。当然每秒fsync一次,性能还是很高的。如果要保证一条数据不丢失,也是可以的。AOFfsync设置如果一条数据没有写入,fsync一次,就结束了,redis的QPS会急剧下降。(3).之前AOF有一个bug,就是通过AOF记录的日志恢复数据时,并没有恢复出完全相同的数据。因此,像AOF这种基于命令log/merge/playback的更复杂的方式,比基于RDB每次持久化一个完整的数据快照文件的方式更脆弱,更容易出现bug。但是AOF是为了避免rewrite过程带来的bug,所以每次rewrite都不会根据旧的指令log进行合并,而是根据当时内存中的数据重建指令,所以健壮性会好很多。(4).唯一比较大的缺点就是做数据恢复的时候会比较慢,而且不方便做冷备份和定时备份。您可能需要自己编写复杂的脚本来进行冷备份。不适合AOF和RDB数据恢复机制AOF,存储的指令日志,在做数据恢复的时候,实际上需要重放执行所有的指令日志,才能恢复RDB内存中的所有数据,这是一个数据文件。恢复时,直接加载到内存中即可。AOF和RDB在redis中都是以文件的形式存在的!!!5.如何选择RDB和AOF(一)。不要只使用RDB,因为那样会导致你丢失大量数据(2)。不要只用AOF,因为有两个问题,***,你用AOF做冷备份,不用RDB做冷备份,恢复速度更快;第二,RDBevery二次简单粗略的数据快照生成更健壮,可以避免AOF这种复杂备份恢复机制的bug(3)。结合使用AOF和RDB两种持久化机制,使用AOF保证数据不丢失,作为数据恢复的***选择;使用RDB进行不同程度的冷备份。当AOF文件丢失或损坏不可用时,也可以使用RDB进行数据的快速恢复6.如何配置RDB持久化(一).redis。conf文件,即/etc/redis/6379.conf,配置持久化。例如:save601000(每隔60s,如果超过1000个key发生变化,则生成一个新的dump.rdb文件,就是当前redis内存中的完整数据快照,这个操作也叫快照,快照也可以手动调用save或bgsave命令,同步或异步执行rdb快照生成)(2).save可以设置为multiple,即多次快照Checkpoint,每到达一个checkpoint,就会检查是否有多少个specifiedkeyshaschanged,如果改变了,会生成一个新的dump.rdb文件7.RDB持久化机制的工作流程(一)。根据配置,redis尝试自己生成rdb快照文件,fork一个子进程,子进程尝试将数据dump到临时的rdb快照文件中。rdb快照文件生成完成后,替换掉之前的旧快照文件dump。rdb,每次生成新的快照,都会覆盖之前的旧快照。8、基于RDB持久化机制的数据恢复实验(一)。在redis中保存几条数据,立即停止redis进程,然后重启redis,看刚才插入的数据是否还在(2)。redis中的redis保存几条新数据,使用kill-9粗略杀掉redis进程,模拟redis故障异常退出导致内存数据丢失的场景。注意:通过redis-cliSHUTDOWN停止redis其实是安全退出9.如何配置AOF持久化(一)。AOF持久化默认关闭,RDB持久化默认开启(2)。appendonly是的,可以开启AOF持久化机制。在生产环境中,一般来说,AOF是必须要开启的,除非你说丢几分钟数据无所谓。启用AOF持久化机制后,redis会在收到写命令后写入日志文件。当然会先写入os缓存,然后定时fsynced。即使AOF和RDB都开启了,当redis重启的时候,也会优先AOF。对于数据恢复,因为aof数据比较完整(3)。AOF的fsync策略是可以配置的。共有三种策略可供选择。一种是每写入一条数据就执行一次fsync;另一种是每秒执行一次fsync;一是不主动执行fsyncalways:每写入一条数据,立即将这条数据对应的logfsync写入磁盘,性能非常非常差,吞吐量非常低;确保redis中的数据没有丢失,那么就只能这样everysec:每秒fsyncos缓存中的数据到磁盘,这个是最常用的,生产环境一般都是这样配置的,性能很高,QPS还是可以上万no:只有redis负责把数据写入os缓存,不用管,然后os自己会有自己的策略把数据刷盘时不时地,这是无法控制的。10、AOF持久化数据恢复实验(一)。首先只是打开RDB写入一些数据,然后kill-9杀掉redis进程,然后重启redis,发现数据没有了,因为RDB快照还没有生成(2)。打开AOF开关并启用AOF持久化(3)。写入一些数据,观察AOF文件(4).kill-9中的日志内容,杀掉redis进程,重启redis进程,发现数据恢复了,是从AOF文件恢复的(redis进程启动届时所有的日志会直接从appendonly.aof中加载,内存中的数据会恢复)注:在appendonly.aof文件中可以看到刚刚写入的日志,实际上是写入了os先缓存。然后1秒后fsync到磁盘,只fsync到磁盘,是安全的,否则只是在os缓存中,只要重启机器,什么都不会丢失11.AOF重写AOF工作原理(一).redisfork一个子进程(2)。子进程根据当前内存中的数据建立日志,并开始将日志写入新的临时AOF文件(3)。redis主进程收到客户端新的写操作,内存中的数据继续写入新的日志到AOF文件,同时新的数据也继续写入旧的AOF文件(4)。redis主进程将内存中新写入的日志追加到新的AOF文件中(5)。用新的日志文件替换旧的日志文件。redis中的数据其实是有限的。很多数据可能会自动过期,可能会被用户删除,也可能会被redis使用缓存清除算法清理掉。redis中的旧数据会不断被淘汰,一些常用的数据会自动保留在redis内存中,所以可能会有很多之前清理过的数据,对应的写入日志还停留在AOF中,AOFlogfile就一个,它会不断扩大,直到变得非常大,所以AOF会每隔一段时间自动在后台进行rewrite操作,比如log已经存储了100w条数据的写日志;redis内存只剩10万;根据内存中当前10万条数据构建一套完整的日志,并放入AOF;覆盖之前的旧日志;保证AOF日志文件不会太大,在redis内存中保持等量的数据。redis2.4之前需要手动,开发一些脚本,crontab,通过BGREWRITEAOF命令执行AOFrewrite,但是redis2.4之后会自动执行rewrite操作注意:在redis.conf中,可以配置rewritestrategyauto-aof-rewrite-percentage100auto-aof-rewrite-min-size64mb比如上次AOFrewrite后是128mb,之后会在128mb继续写AOF日志。如果发现增长比例超过了之前的100%,也就是256mb,可能会触发rewrite,不过这个时候还是要和min-si谈谈ze,64mb比较,256mb>64mb,会触发rewrite12.AOF损坏文件修复如果redis在向AOF文件追加数据时机器死机,可能是AOF文件损坏,使用redis-check-aof--fix命令修复损坏的AOF文件13、AOF和RDB同时工作(1)。如果RDB正在进行快照操作,则redis不会进行AOFrewrite;如果redis再次进行AOFrewrite,则不会进行RDB快照(2)。如果RDB正在执行快照,此时用户执行BGREWRITEAOF命令,然后等到RDB快照生成后再执行AOFrewrite(3)。既有RDB快照文件,也有AOF日志文件,所以当redis重启时,会优先使用AOF进行数据恢复,因为其中日志比较完整14.企业级持久化配置策略在企业中,RDB生成策略是几乎和默认的一样save6010000:如果要保证RDB最多丢失1分钟的数据,那么尽量每1分钟生成一次快照。非高峰期,数据量小,不需要开启AOF。fsync,everysecauto-aof-rewrite-percentage100:表示当前AOF大小已经扩大到上次超过100%。auto-aof-rewrite-min-size64mb的两倍:根据你的数据量,16mb,32mb15。企业级数据备份解决方案(一)。编写crontab定时调度脚本做数据备份(二)。每小时复制一个rdb备份到一个目录,并且只保留最近48小时的备份(3)。每天保留一份rdb备份,转到一个目录,只保留最后1个月(4)。每次复制备份时,删除太旧的备份(5)。每天晚上,您将备份当前服务器上的所有数据,并每小时发送一份副本到远程云服务每天同一时间每小时备份,删除48小时前的数据/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/6379/转储.rdb/usr/local/redis/snapshotting/$cur_date del_date=`date-d-48hour+%Y%m%d%k` rm-rf/usr/local/redis/snapshotting/$del_date 每天备份一次 crontab-e 00***sh/usr/local/redis/copy/redis_rdb_copy_daily.sh 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/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每天一次将所有数据上传到远程云服务器16.企业级数据恢复方案(一)。如果redis进程挂了,重启redis进程,直接根据AOF日志文件恢复数据(2)。如果redis进程所在的机器挂了,那么重启机器后,尝试重启redis进程,直接根据AOF日志文件尝试恢复数据,前提是AOF没有损坏,AOFappend-only,依次写入,如果AOF文件损坏,则使用redis-check-aoffix进行修复(3)。如果redis当前的AOF和RDB文件丢失/损坏,那么可以尝试在机器上根据当前的RDB数据进行复制,进行数据恢复,当前AOF和RDB文件丢失/损坏到无法恢复。一般不是机器故障,而是人为的。17、容灾演练appendonly.aof+dump.rdb,首先使用appendonly.aof恢复数据。(1).如果关闭AOF持久化机制,dump.rdb有数据,此时重启redis,发现内存中明显没有恢复数据。原因:redis启动时自动根据内存数据重新生成一个***rdb快照,直接用空数据覆盖我们有数据的dump.rdb(2)。如果启用了AOF,停止redis后,先删除appendonly.aof,然后复制我们的dump.rdb,然后重启redis,发现数据还是没有恢复原因:虽然你删除了appendonly.aof,但是因为aof持久化是enabled,redis必须是会优先基于aof进行恢复,即使文件不存在,然后新建一个空的aof文件(3)。停止redis,在配置中暂时关闭aof,然后复制一份rdb,然后重启redis,此时内存中的数据恢复成功;一不小心,关掉redis,手动修改配置文件,打开aof,再重启redis,数据又没了,因为是空aof文件,所以数据全没了。在数据安全丢失的情况下,基于rdb冷备份,如何完整恢复数据,同时保持aof和rdb双开?(4).停止redis,关闭aof,复制rdb备份,重启redis,确认数据恢复,直接在命令行修改redis配置,开启aof,这个redis会将内存中数据对应的log写入aof文件。这时aof和rdb这两个数据文件的数据就会同步。注意:redisconfigset热修改配置参数。可能配置文件中的实际参数没有被持久化修改。再次停止redis,手动修改配置文件,打开aof命令,再次重启redis(5)。如果当前机器的RDB文件全部损坏,则从远程云服务中拉取最新的RDB快照并恢复数据(6)。如果发现重大数据错误,比如某个时间点上线的程序突然删除了所有数据污染,数据全错了,那么可以选择更早的时间点恢复数据比如代码12点启动,发现代码有bug,导致代码生成的缓存数据全部写入redis,全错,11点找一个rdb的冷备份,然后按照以上步骤将数据恢复到11点。
