Redis的持久化

Redis虽然是基于内存的存储系统,但是它本身是支持内存数据的持久化的,而且提供两种主要的持久化策略:
RDB快照AOF日志

 

下面分别介绍这两种不同的持久化策略:
1、Redis的RDB快照

       Redis支持将当前数据的快照存成一个数据文件的持久化机制,即RDB快照。这种方法是非常好理解的,但是一个持续写入的数据库如何生成快照呢?
       Redis借助了fork命令的copy on write机制(私有内存非共享内存)。在生成快照时,将当前进程fork出一个子进程,然后在子进程中循环所有的数据,将数据写成为RDB文件。

       我们可以通过Redis的save指令来配置RDB快照生成的时机,比如你可以配置当10分钟以内有100次写入就生成快照,也可以配置当1小时内有 1000次写入就生成快照,也可以多个规则一起实施。这些规则的定义就在Redis的配置文件中,你也可以通过Redis的CONFIG SET命令在Redis运行时设置规则,不需要重启Redis。

        在redis中配置:

        1、save  900 1              #当900秒内有一条Keys数据被改变时,生成RDB;
        2、save 300  10            #当300秒内有10条Keys数据被改变时,生成RDB;
        3、save 60    10000     #当60秒内有10000条Keys数据被改变时,生成RDB;

 

RDB文件会坏掉吗?

       Redis的RDB文件不会坏掉,因为其写操作是在一个新进程中进行的,当生成一个新的RDB文件时,Redis生成的子进程会先将数据写到一个临时文件中,然后通过原子性rename系统调用将临时文件重命名为RDB文件,这样在任何时候出现故障,Redis的RDB文件都总是可用的。

(

同时,Redis 的RDB文件也是Redis主从同步内部实现中的一环。

第一次、Slave向Master同步的实现是:
        Slave向Master发出同步请求,Master先dump出rdb文件,然后将rdb文件全量传输给slave,然后Master把缓存的写命令转发给Slave,初次同步完成。
第二次、以及以后的同步实现是:
        Master将变量的快照直接实时依次发送给各个Slave。
        但不管什么原因导致Slave和Master断开重连都会重复以上两个步骤的过程。
        Redis的主从复制是建立在内存快照的持久化基础上的,只要有Slave就一定会有内存快照发生。      

)

但是,我们可以很明显的看到,RDB有他的不足,就是一旦Redis出现问题,那么我们的RDB文件中保存的数据并不是全新的,从上次RDB文件生成到 Redis停机这段时间的数据全部丢掉了。在某些业务下,这是可以忍受的,我们也推荐这些业务使用RDB的方式进行持久化,因为开启RDB的代价并不高。 但是对于另外一些对数据安全性要求极高的应用,无法容忍数据丢失的应用,RDB就无能为力了,所以Redis引入了另一个重要的持久化机制:AOF日志。

 

2、 Redis的AOF日志
         AOF日志的全称是append only file,从名字上我们就能看出来,它是一个追加写入的日志文件。与一般数据库的binlog不同的是,AOF文件是可识别的纯文本,它的内容就是一个个 的Redis标准命令。当然,并不是发送到Redis的所有命令都要记录到AOF日志里面,只有那些会导致数据发生修改的命令才会追加到AOF文件

 

那么每一条修改数据的命令都生成一条日志,那么AOF文件是不是会很大?
        答案是肯定的,AOF文件会越来越大,所以Redis又提供了一个功能,叫做AOF rewrite(使用Redis提供了bgrewriteaof命令就可以)。
其功能就是重新生成一份AOF文件,新的AOF文件中一条记录的操作只会有一次,而不像一份老文件那样,可能记录了对同一个值的多次操作。其生成过程和RDB类似,也是fork一个进程,直接遍历数据,写入新的AOF临时文件(这个过程和RDB类似,但是是将数据拆分成一条一条写命令的形式的在写入新文件的过程中,所有的写操作日志还是会写到原来老的 AOF文件中,同时还会记录在内存缓冲区中。当重完操作完成后,会将所有缓冲区中的日志一次性写入到临时文件中。然后调用原子性的rename命令用新的 AOF文件取代老的AOF文件。(这样的操作,老的AOF可以恢复内存,如果产生新的AOF,老的就不存在了,可用新的AOF文件恢复内存,这样同时解决了AOF不断增长的问题。)AOF是一个写文件操作,其目的是将操作日志写到磁盘上,所以它也同样会遇到我们上面说的写操作的5个流程。

 

那么写AOF的操作安全性又有多高呢?

实际上这是可以设置的,在Redis中对AOF调用write(2)写入后,何时再调用fsync将其写到磁盘上,通过appendfsync选项来控制,下面 appendfsync的三个设置项,安全强度逐渐变强。

1)appendfsync no
        当设置appendfsync为no的时候,Redis不会主动调用fsync去将AOF日志内容同步到磁盘,所以这一切就完全依赖于操作系统的调试了。对大多数Linux操作系统,是每30秒进行一次fsync,将缓冲区中的数据写到磁盘上

2)appendfsync everysec
        当设置appendfsync为everysec的时候,Redis会默认每隔一秒进行一次fsync调用,将缓冲区中的数据写到磁盘。但是当这一次的fsync调用时长超过1秒时。Redis会采取延迟fsync的策略,再等一秒钟。也就是在两秒后再进行fsync,这一次的fsync就不管会执行多 长时间都会进行。这时候由于在fsync时文件描述符会被阻塞,所以当前的写操作就会阻塞。

        结论就是,在绝大多数情况下,Redis会每隔一秒进行一 次fsync。在最坏的情况下,两秒钟会进行一次fsync操作。这一操作在大多数数据库系统中被称为group commit,就是组合多次写操作的数据,一次性将日志写到磁盘。

3)appendfsync always
        置appendfsync为always时,每一次写操作都会调用一次fsync,这时数据是最安全的,当然,由于每次都会执行fsync,
所以其性能也会受到影响。


 

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

你可能感兴趣的:(redis)