Redis的持久化

Redis两种不同持久化方式

Redis提供了不同方式对数据进行持久化:
1、RDB模式按照指定时间间隔记录数据集在某个时间点的快照;
2、AOF模式会记录服务器接收的每个写入操作,这些操作将在服务器启动时被加载以重建原始数据集。 使用与Redis协议本身相同的格式记录命令并只允许追加写入的方式。 当记录的日志太大时,Redis可以在后台重写日志;
3、如果仅仅希望数据只在服务器运行时存在,没有持久化的需求,则可以禁用持久化的功能;
4、Redis也支持在同一实例当中同时使用RDB和AOF持久化的方式,需要注意的是在这种情况下Redis服务器重启时将会加载AOF日志文件以重建数据集,因为AOF日志文件可以保证构造出的数据集是最完整的;

RDB模式与AOF模式之间的优劣点:
RDB的优点:
1、RDB以一种紧凑单文件方式记录某个时间点数据库中的数据集。RDB的文件非常适合用于备份。假如你希望在最近24小时之内每小时都备份一次数据,并且在30天之内每天保存一次RDB的快照,那么在灾后恢复时你可以轻松选择不同版本的数据集进行恢复。
2、RDB非常有利于灾后的数据恢复,因其为单文件且内容紧凑可被传输到远程数据中心;
3、RDB最大限度地提高Redis的服务能力,在持久化过程中Redis进程会启动一个子进程来处理持久化的工作,而父进程将永远不会执行类似于磁盘I/O的操作;
4、RDB在启动时加载大数据量数据的速度相较于AOF会高很多;
RDB的缺点:
1、当Redis服务停止工作(例如断电)之后,如果你希望丢失数据的数据最少,那么RDB可能不是一个好的选择。你可以配置不同的触发条件[点](save point)来触发RDB文件的产生(例如5分钟之内产生100次写操作并且你可以配置多个条件),但是一般都是5分钟或者更长时间创建一次RDB快照文件,所以Redis服务器在未正常关闭的情况下就可能会丢失几分钟之内的数据;
2、RDB持久化时父进程会通过fork()函数创建一个子进程来实际处理持久化操作。在数据集很大的情况下,fork()操作需要的时间也将更长一些,在这种情况下如果主机的cpu性能不佳,则可能导致Redis对客户端停止服务1毫秒甚至1秒钟。AOF虽然也存在fork()的操作,但是其可以控制重写日志的频率而无需权衡持久性(RDB达到条件就会触发);

AOF的优点:
1、AOF持久化方式更多样,可以配置不同的刷新磁盘策略:从不刷新(fsync)/每秒刷新(fsync)一次/每次写操作刷新(fsync)。使用默认策略(每秒刷新一次)在最坏情况下也仅仅会丢失一秒内的数据(fsync操作是在后台开启单独线程进行处理,在没有fsync操作时主线程尽力执行写操作);
2、AOF日志仅在文件后追加内容,故这里不存在文件损坏或磁盘寻道错误的情况存在。即使在极端情况下命令写入到一半(磁盘写满或断电等情况),也可以通过使用redis-check-aof工具对AOF日志进行修复;
3、Redis针对AOF日志太大的情况会在后台开启单独线程对日志进行重写操作()。重写的操作是一个安全的操作,新的日志依然会追加到原来的日志文件中,redis会重新生成一个文件针对原日志文件进行重写(主要是针对一些命令进行合并,比如对同一个变量多次赋值或者flushall操作等),重写完毕之后会将原日志追加到新的日志当中;
4、AOF以一个人类易于理解和解析的格式进行存储日志,同时也可以轻松地对日志进行导出。假如你错误地使用了flushall命令将Redis的数据进行了清除并且在此期间Redis没有触发重写日志,那么你可以停止Redis服务器,将AOF文件最后一条命令删除并重启Redis服务器,数据就可以恢复到执行flushall之前的状态;

AOF的缺点:
1、在相同数据集下,AOF文件要比RDB文件要大;
2、在特定的fsync策略上,AOF的性能可能比RDB要慢。一般fsync使用每秒更新策略的情况下AOF的性能仍然很高,而在禁用fsync的高负载情况下,AOF的性能应该与RDB的情况一样快。另外RDB能够提供更多在高负载下的最低延迟的保证;
3、过去在执行某些特定命令(例如阻塞命令BRPOPLPUSH))会产生一些少见的bug–通过使用AOF重新载入数据导致数据集不完全。但是这些问题在RDB当中根本就不存在。为了更清除地说明这一点,Redis AOF的工作原理是通过现有状态进行增量更新,就如同MySQL与MongoDB一样。而RDB快照则一次又一次地重新创建,这样相比较而言也更加健壮。另外Redis对AOF进行重写也是在之前历史的日志之上进行重新创建,这样与仅仅追加新操作命令到原文件当中,其健壮性更强。

我们应该如何选择?

通常如果你希望获得与PostgreSQL差不多的数据安全性,建议在实际使用中两种同步方式一起使用。如果你很在意你的数据并且能够接受少量数据的丢失,那么只使用RDB模式不失为一种好的方案。相比单独使用RDB,很多用户更加倾向于单独使用AOF,但是我们更鼓励使用RDB进行数据的备份,不仅仅因为RDB重启时数据加载速度更快,另外还因为AOF引擎存在的一些bug。
注意:综合RDB与AOF的特性,将来可能将RDB与AOF合并为一种持久化模型来使用。

1、RDB快照

默认情况下Redis会开启RDB持久化功能,会生成一个名为dump.rdb的二进制格式的文件。你可以配置在N秒内发生M次写入操作时触发Redis持久化,或者你直接调用SAVEBGSAVE命令主动触发持久化。以下面这个配置为例,如果Redis在60秒内发生1000次写入操作将会触发持久化动作:

save 60 1000

RDB持久化工作方式:
1)、Redis执行fork操作,此时会存在父进程及一个子进程;
2)、子进程开始将原文件数据与发生变更的数据写入到一个临时文件中;
3)、当子进程写文件的操作完成后,会使用新的临时文件替换原RDB文件;
Redis使用写时复制(copy-on-write)的方式处理RDB文件。

2、AOF

在Redis服务器挂掉、服务器断电,或者意外地被执行kill -9,那么RDB快照方式持久化的数据可能会丢失最近的一些数据而导致日志文件记录的数据不完整。这种情况对于某些应用可能没什么太大的影响,但是对于那些要求日志完整性要求高的应用来说就不是一个好的选择了。
AOF则是对日志完整性要求高的场景的一种选择。该特性在1.1版本提供,启用该特性只需要在配置文件当中配置如下:

appendonly yes

开启之后每次Redis接收到写入操作(例如SET命令)时都将会将变更信息追加到AOF文件;而在重启Redis之后将会通过读取AOF文件对数据进行一次重建。

日志重写:
正如你所想,AOF文件会在一次次的写入操作之下变的越来越大。举例来说,假如你针对同一个key循环设值100次,在Redis当中该key的值只有一个,而在AOF当中有100条设值记录,在Redis重启时重建缓存时对key同样会操作100次。所以Redis推出了一个有趣的特性:Redis可以在后台重写AOF日志而无需中断对客户端的服务。当你触发BGREWRITEAOF命令时,Redis将以一个最简短的命令来重写内存中的数据及。如果你使用的是2.2版本的Redis,那么你需要每次手动触发该命令,而2.4及以上版本则会自动触发重写操作。

AOF持久化的几种策略:
1、改动就触发(appendfsync always):每次在AOF文件增加一条日志就触发一次fsync,这会很慢但是数据很安全;
2、每秒钟触发(appendfsync everysec):每秒触发一次fsync,最多丢失一秒内的数据;
3、不触发持久化动作(appendfsync no):不会触发fsync,数据直接由操作系统处理,该策略对于AOF持久化来讲最快但是是最不安全的。在此配置下Linux系统默认30秒触发一次刷新操作,但是具体情况也需要看内核的调度;
Redis建议的也是默认的策略是每秒钟触发一次,因为它不仅比较快还比较安全。而有改动就触发同步的策略在实践当中表现的速度很慢,但是其支持批量组提交,如果有多个并行写入,那么Redis将尝试执行单个fsync。

AOF文件数据被截断如何处理:
在写入AOF时Redis服务挂掉或者AOF文件所在磁盘空间不足导致的数据丢失都是完全有可能发生的事情,在这种情况下AOF文件仍包含一个给定时间点及之前的数据,但是AOF文件最后一条命令可能被截断了,在Redis最新主版本中仍然能够加载AOF文件并且会丢弃最后一个错误的命令。Redis服务会打印如下日志:

* Reading RDB preamble from AOF file...
* Reading the remaining AOF tail...
# !!! Warning: short read while loading the AOF file !!!
# !!! Truncating the AOF at offset 439 !!!
# AOF loaded anyway because aof-load-truncated is enabled

当然你可以更改配置文件当遇到AOF文件命令错误时直接停止服务,但是默认情况Redis服务是不管最后一条命令是否正确都将继续执行,这也是为了保证在Redis重启之后的可用性。
老版本的Redis可能不会自动恢复,可以通过以下步骤恢复AOF文件可被加载:
1)、对AOF文件进行备份;
2)、针对源文件使用redis-check-aof工具进行修复:

$ redis-check-aof --fix xxxx

3)、修复完成之后可使用diff -u命令来对比下两个文件的差异之处;
4)、使用修复之后文件重启Redis服务;

AOF文件损坏了如何处理:
如果AOF文件不仅仅是数据被截断,而是更复杂点的,在AOF文件中插入不合法的字符序列,这时Redis在启动时会提示如下错误并终止服务:

* Reading the remaining AOF tail...
# Bad file format reading the append only file: make a backup of your AOF file, then use ./redis-check-aof --fix <filename>

最好的办法就是不带–fix参数运行redis-check-aof程序,程序会提示文件哪里存在问题,如果这个问题比较简单,可以找到文件错误的位置手动进行修复,因为AOF文件也是遵循Redis协议,所以很容易理解。如果直接使用–fix参数让程序自动进行修复的话,那么失效部分到文件末尾部分的内容都将丢弃,如果在丢弃的这部分存在大量数据,那么最终将完全丢失这部分数据。

AOF文件重写的工作机制:
AOF重写同样使用了写时复制(copy-on-write)的技巧。
1)、Redis执行fork操作,此时会存在父进程及一个子进程;
2)、子进程开始将原文件写入到一个临时文件;
3)、父进程会以增量的方式将新的变更写入到内存缓冲区(同时也会将新的变更追加到老的文件当中,如果重写失败,数据依然是安全的);
4)、当子进程完成重写日志的任务会发一个信号给到父进程,父进程在接收到子进程的信号之后会将内存缓冲区的变更追加到子进程重写的日志之后;
5)、Redis将原文件重命名为新的文件并且新的写入数据都将追加到新文件之后;

3、AOF与RDB之间的交互:

Redis在2.4及其之上的版本能够避免AOF重写与RDB操作同时进行,或者BGSAVE与AOF重写的同时进行。这能够避免Redis两个后台进程同时进行大量的磁盘操作。当RDB正在运行时,用户发出日志重写的BGREWRITEAOF命令时,Redis服务将会返回OK的状态表示该命令已经在等待调度,当RDB完成之后将会被调度执行。
在同时启用AOF和RDB并重启Redis服务时,Redis将会加载AOF文件重建缓存数据,因为AOF文件记录的日志能保证更加完全一点。

4、备份Redis数据:

硬盘损坏、服务实例不可用等都将意味着Redis数据丢失,所以你需要确认数据是否存在备份。对Redis数据进行备份很方便,在Redis服务运行时即可备份,因为RDB文件一旦产生将不再变动,新的临时文件在同步完成之后会重命名目标文件名。这里给出以下建议:

在服务器上创建一个cron任务,在一个目录中创建RDB文件的每小时快照,并在另一个文件中创建每日快照;
在每次执行cron任务时要确保调用find命令查看很久之前的快照已经被删除,举例来说可以保存48小时之内的每小时快照,并保存1到2个月的每日快照。确保快照命名是以日期加时间来辨识的;
每天要确保将快照从数据中心或者至少从物理机上迁移到外部;

如果仅仅是开启了AOF,你依然可以复制AOF文件作为备份数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值