Redis提供的持久化就是将内存中的数据保存到磁盘内,避免服务中断造成数据丢失问题,下次重启可以通过持久化的文件进行恢复。Redis持久化分为RDB和AOF两种机制:

一、RDB持久化

1.1 RDB是什么

RDB持久化是通过给当前内存中的数据生成内存快照,然后保存到磁盘的过程,这就像是拍照片一样,可以将某一时刻的状态留存下来,需要注意的是,RDB针对的是全量数据,这意味着,数据量越大,生成内存快照所需要的开销就会越大!!

1.2 怎么开启RDB

想要生成RDB快照文件,可以手动执行命令,也可以通过配置的方式自动生成,先来看手动的命令。Redis提供了如下两个命令:

save:该命令是借助主线程来生成快照文件,会阻塞主线程,不建议在生产环境上使用;

bgsave:这个命令不会阻塞主线程,而是创建一个子进程用于生成快照文件,也是Redis的默认配置;

127.0.0.1:6379> save

OK

127.0.0.1:6379> bgsave

Background saving started

127.0.0.1:6379>

生成的快照文件dump.rdb的位置需要看你redis.conf里面dir的配置,文件名的话则是看dbfilename这个配置。

除了手动执行命令,我们也可以通过配置的方式来实现自动触发生成。

# 3600秒内发生至少一次写操作,会触发bgsave

save 3600 1

# 300秒内发生至少100次写操作,会触发bgsave

save 300 100

# 60秒内发生至少10000次写操作,会触发bgsave

save 60 10000

还有一些特殊场景,也可以触发bgsave:

1.如果从节点执行全量复制操作,主节点会自动触发bgsave生成RDB文件并发送给从节点;

2.执行debug reload重新加载Redis时;

3.默认情况下执行shutdown命令时(未开启AOF持久化)

如果不想开启RDB持久化的话,可以修改配置如下:

save ""

1.3 bgsave的执行流程

上面是bgsave执行的流程图,需要注意的是:如果在子进程生成快照的时候,主线程要对数据进行修改,那么会通过写时复制(Copy-On-Write,COW)技术拷贝一份副本,将它保存到我们的快照文件当中。

1.4 RDB的优缺点

RDB每次生成的快照文件都是基于全量数据,数据恢复的速度会快于AOF的方式,但是它无法做到实时的持久化,不仅因为针对的是全量数据,同时每次都要单独创建一个子进程来处理,这个开销会比较大,我们可以每隔几个小时去做一次bgsave,生成全量备份,然后把文件放到备份机器上,方便灾后恢复。除此之外,RDB的持久化还存在数据丢失的问题,因为无法做到实时持久化,所以如果两次持久化中间时段一旦发生宕机,那么这段时间之内发生的数据修改就全部丢失了,因为上一次的快照文件当中没有对应的数据。

二、AOF持久化

2.1 AOF是什么

AOF(Append Only File)以日志的形式来记录每次写命令,这样Redis重启的时候只需要执行AOF文件内保存的命令即可达到恢复数据的目的,它解决了上面RDB无法达到实时持久化的问题。如果想要开启AOF的话,我们需要修改如下配置:

#appendonly默认为no,不开启,开启的话只需要改成yes即可

appendonly yes

开启AOF之后,写入文件也会被存放在dir指定的目录下面,文件名默认为appendonly.aof,可以通过如下配置进行修改:

appendfilename "appendonly.aof"

2.2 AOF工作流程

AOF的整体工作流程如上图所示,当我们执行写命令的时候,Redis会以RESP文本协议格式将写命令追加到AOF缓冲区内,而后再基于采用的AOF缓冲同步策略将缓冲区的内容同步到文件当中,Redis提供了三种不同的缓冲同步策略,我们可以通过如下配置进行修改:

# 1.always表示每次写命令执行完,就会立即同步到文件中

appendfsync always

# 2.everysec表示每一秒将缓冲区内容同步到文件中

appendfsync everysec

# 3.no不代表不同步到文件,只是同步操作由操作系统把控,同步周期最长一般为30s

appendfsync no

很明显,如果配置为always,AOF缓冲区的意义就不大了,配置为no的话同步周期不可控,一般建议配置为everysec,这个也是默认的配置。

当AOF文件随着不断写入变得越来越大,会触发AOF重写,AOF重写机制是将当前进程内的数据转换为写命令后同步到新AOF文件的过程,AOF重写不仅可以减少文件的体积,同时在Redis重启加载时也能更加迅速。AOF重写主要基于如下几点:

进程内某些已经超时的数据是不需要再写入文件的;

旧的AOF文件包含无效命令如set name zs和set name ls,AOF重写是以当前进程内的最终数据转换为写命令写入到文件内;

部分命令可以进行合并变成一条,比如lpush stu zs和lpush stu ls可以合并为lpush stu zs ls

AOF重写分为手动触发和自动触发两种,手动触发的话只需要在客户端执行如下命令:

127.0.0.1:6379> bgrewriteaof

Background append only file rewriting started

AOF重写自动触发需要同时满足下面两个条件:

# AOF执行重写的最小文件体积

auto-aof-rewrite-min-size 64mb

# AOF文件增长率的阈值,当前文件大小必须>=(1+percentage/100)*上次重写后文件大小,才会触发重写

auto-aof-rewrite-percentage 100

另外,如果在Redis在进行AOF重写时,有写入操作,这个操作也会被写到重写日志的缓冲区。这样,重写日志也不会丢失最新的操作。

Redis重启的时候,会先看是否开启了AOF,如果是的话则优先加载AOF文件,如果没有,则加载RDB文件,加载完毕,Redis成功启动,如果加载失败的话(文件可能损坏),则会启动失败并打印错误信息!

2.3 RDB-AOF混合持久化

在4.0之后,AOF重写时可以选择混合持久化模式,这种模式不同的地方在于,子进程在进行重写的时候会先以RDB的格式将当前数据快照写入到AOF文件头部,而后再将重写期间的增量命令以AOF格式追加到AOF文件尾部,这样既能保证恢复速度快(RDB优势),又能保证数据丢失少(AOF优势)。我们可以如下配置来开启混合持久化:

aof-use-rdb-preamble yes