Redis持久化的两种方式

参考:

         http://blog.csdn.net/canot/article/details/52886923

         http://blog.csdn.net/yangyutong0506/article/details/46880773
目前Redis持久化的方式有两种: RDB 和 AOF。
首先,我们应该明确持久化的数据有什么用,答案是用于重启后的数据恢复。Redis是一个内存数据库,无论是RDB还是AOF,都只是其保证数据恢复的措施。所以Redis在利用RDB和AOF进行恢复的时候,都会读取RDB或AOF文件,重新加载到内存中。

一、RDB(Redis DataBase)持久化

1、是什么?
RDB就是Snapshot快照存储,是默认的持久化方式。指在指定的时间间隔内将内存中的数据集快照写入磁盘,对应产生的数据文件为dump.rdb。当服务启动时将该dump.rdb文件直接读到内存里,实现数据的恢复。通过配置文件中的save参数来定义快照的时间间隔:
save 900 1    #当有一条Keys数据被改变时,900秒刷新到Disk一次
save 300 10   #当有10条Keys数据被改变时,300秒刷新到Disk一次
save 60 10000 #当有10000条Keys数据被改变时,60秒刷新到Disk一次
2、原理?
当生成一个新的RDB文件时,Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件(通过原子性rename系统调用将临时文件重命名为RDB文件)。由于其写操作是在一个新进程中进行的,这样在任何时候出现故障,Redis的RDB文件都总是可用的。

fork:fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程

整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能。如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失

3、如何触发RDB快照存储?
1)第1点提到的,按照配置文件中的save参数。比如若在300秒内发生了10条keys数据的改变时会触发,满足触发条件时执行shutdown命令后会产生dump.rdb文件,保存在本次启动服务的目录下。需要注意的是:若在执行shutdown前执行了flushall这个命令,则产生的dump.rdb文件是空的。
2)执行save命令:save命令执行后立即产生dump.rdb文件。save时只管保存,其他不管,全部阻塞。
     执行bgsave命令:Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。可以通过lastsave命令获取最后一次成  功执行快照的时间
3)执行flushall命令:此时也会产生dump.rdb文件,但是里面是空的,无意义

4、RDB存储的优势?

1)适合大规模的数据恢复
2)对数据完整性和一致性要求不高
3)RDB的启动时间会更短
原因有两个:
一是RDB文件中每一条数据只有一条记录,不会像AOF日志那样可能有一条数据的多次操作记录。所以每条数据只需要写一次就行了。
另一个原因是RDB文件的存储格式和Redis数据在内存中的编码格式是一致的,不需要再进行数据编码工作,所以在CPU消耗上要远小于AOF日志的加载

5、RDB存储的劣势?

1)在一定间隔时间做一次备份,所以如果redis意外故障的话,就会丢失最后一次快照时间间隔的所有修改
2)fork的时候,内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑

二、AOF(Append Only File)持久化
1、是什么?

Redis AOF是类似于log的机制,每次写操作都会写到硬盘上,当系统崩溃时,可以通过AOF来恢复数据。每个带有写操作的命令被redis服务器端收到运行时,该命令都会被记录到AOF文件上。由于只是一个append到文件操作,所以写到硬盘上的操作往往非常快

2、原理?

以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。(如果aof持久化方式被启用的话)

3、如何启动aof存储方式?(因为默认的是rdb存储,aof关闭状态)

在配置文件中设置参数:
appendonly yes       #启用AOF持久化方式(默认no)
appendfilename appendonly.aof #AOF文件的名称,默认为appendonly.aof
只要在redis服务重新启动时则会加载appendonly.aof文件,实现数的恢复
若AOF日志文件出错后,修复方法 :
redis-check-aof --fix appendonly.aof  #--fix参数为修复日志文件,不加则对日志检查

4、AOF存在的问题?
AOF的完全持久化方式会使持久化文件会变得越来越大。比如我们调用INCR test命令100次,文件中就必须保存全部的100条命令,但其实99条都是多余的。因为要恢复数据库的状态其实文件中保存一条SET test 100就够了。为了压缩AOF的持久化文件,Redis提供了bgrewriteaof(自动的)重写命令。

bgrewriteaof重写原理:AOF文件持续增长而过大时,会fork出一条新进程来将文件重写(也是先写入临时文件最后再rename),遍历新进程的内存中数据,合并set命令等操作到一个临时文件(去除多余的写命令),这点和快照有点类似。

重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件用于追加后续的记录。(这样就减少了类似于那99条多余的命令的多余的命令来达到减小aof文件的大小,因为重写之后aof文件会保存keys的最后的状态,清除掉之前冗余的,来缩小这个文件)

对应的设置参数为:

no-appendfsync-on-rewrite yes   #在日志重写时,不进行命令追加操作,而只是将其放在缓冲区里,避免与命令的追加造成DISK IO上的冲突。
auto-aof-rewrite-percentage 100 #当目前的AOF文件大小超过上一次重写文件大小的百分之几时进行重写(100即两倍),
                                 如果没有重启过,则以启动时的AOF文件大小为依据
auto-aof-rewrite-min-size 64mb  #当前AOF文件启动新的日志重写过程的最小值,避免刚刚启动Reids时由于文件尺寸较小导致频繁的重写。

#################################摘自大佬原话###################################

其实Redis aof机制包括了两件事,rewrite和AOF。rewrite类似于普通数据库管理系统日志恢复点,当AOF文件随着写命令的运行膨胀时,当文件大小触碰到临界时,rewrite会被运行。
rewrite会像replication一样,fork出一个子进程,创建一个临时文件,遍历数据库,将每个key、value对输出到临时文件。输出格式就是Redis的命令,但是为了减小文件大小,会将多个key、value对集合起来用一条命令表达。在rewrite期间的写操作会保存在内存的rewrite buffer中,rewrite成功后这些操作也会复制到临时文件中,在最后临时文件会代替AOF文件。
以上在AOF打开的情况下,如果AOF是关闭的,那么rewrite操作可以通过bgrewriteaof命令来进行。

自动的bgrewriteaof

为了避免aof文件过大,我们会周期性的做bgrewriteaof来重整aof文件。以前我们会额外的配置crontab在业务低峰期执行这个命令,这额外的增加一个workaroud的脚本任务在大集群里是很糟糕的,不易检查,出错无法即时发现。

于是这个自动bgrewriteaof功能被直接加到redis的内部。首先对于aof文件,server对象添加一个字段来记录aof文件的大小server.appendonly_current_size,每次aof发生变化都会维护这个字段。

#################################摘自大佬原话###################################

AOF rewrite操作就是“压缩”AOF文件的过程,当然redis并没有采用“基于原aof文件”来重写的方式,而是采取了类似snapshot的方式:基于copy-on-write,全量遍历内存中数据,然后逐个序列到aof文件中。因此AOF rewrite能够正确反应当前内存数据的状态,这正是我们所需要的;*rewrite过程中,对于新的变更操作将仍然被写入到原AOF文件中,同时这些新的变更操作也会被redis收集起来(buffer,copy-on-write方式下,最极端的可能是所有的key都在此期间被修改,将会耗费2倍内存),当内存数据被全部写入到新的aof文件之后,收集的新的变更操作也将会一并追加到新的aof文件中,此后将会重命名新的aof文件为appendonly.aof,此后所有的操作都将被写入新的aof文件。如果在rewrite过程中,出现故障,将不会影响原AOF文件的正常工作,只有当rewrite完成之后才会切换文件,因为rewrite过程是比较可靠的。

触发rewrite的时机可以通过配置文件来声明,同时redis中可以通过bgrewriteaof指令人工干预。

###############################################################################

5、什么时候触发?

Redis会记录上次重写时的AOF大小,默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发,由上面配置参数可知

6、AOF存储的优势?
AOF是文件操作,对于变更操作比较密集的server,那么必将造成磁盘IO的负荷加重。此外Linux对文件操作采取了“延迟写入”手段,即并非每次write操作都会触发实际磁盘操作,而是进入了buffer中,当buffer数据达到阀值时触发实际写入(也有其他时机),这是linux对文件系统的优化,但是这却有可能带来隐患,如果buffer没有刷新到磁盘,此时物理机器失效(比如断电),那么有可能导致最后一条或者多条aof记录的丢失。通过上述配置文件,可以得知redis提供了3中aof记录同步选项,选择最佳的同步方式:
# appendfsync always #每次收到写命令就立即强制写入磁盘,是最有保证的完全的持久化,但速度也是最慢的,一般不推荐                      不推荐使用。
appendfsync everysec #每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,是受推荐的方式。
# appendfsync no     #完全依赖OS的写入,一般为30秒左右一次,性能最好但是持久化最没有保证,不被推荐。
7、AOF存储的劣势?
1)相同数据集的数据而言aof文件要远大于rdb文件,恢复速度慢于rdb
2)aof运行效率要慢于rdb,每秒同步策略效率较好,不同步效率和rdb相同

三、两种持久化方式的选择

1)通常,如果你要想提供很高的数据保障性,那么建议你同时使用两种持久化方式。需要注意的是,当两种存储方式同时存在时,redis服务启动后是先使用aof方式的。

2)如果你可以接受灾难带来的几分钟的数据丢失,那么你可以仅使用RDB。
3)如果对数据完整性和一致性要求高,那么可以使用AOF
4)不重启redis从RDB持久化切换到AOF持久化 :
redis-cli> CONFIG SET appendonly yes      #启用AOF
redis-cli> CONFIG SET save ""         #关闭RDB
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值