为什么要持久化

Redis是内存数据库,宕机后数据会消失,Redis重启后快速恢复数据,要提供持久化机制。

Redis的两种持久化方式:RDB和AOF

Redis持久化不保证数据的完整性,有可能会丢数据。当Redis用作DB时,DB数据要完整,所以一定要有一个完整的数据源(文件、mysql),在系统启动时,从这个完整的数据源中将数据load到Redis中。

RDB持久化

RDB(Redis DataBase Backup file),是redis默认的存储方式,RDB方式是通过快照( snapshotting )完成的。它保存的是某一时刻的数据并不关注过程。RDB保存redis某一时刻的数据的快照,快照文件称为RDB,默认保存在当前运行目录

触发快照的方式

1. 符合自定义配置的快照规则;

2. 执行save或者bgsave命令;

3. 执行flushall命令;

4. 执行主从复制操作 (第一次)。

保存方式:

1.

Redis的数据持久化_子进程

由Redis主进程来执行RDB会阻塞所有的命令

2.

Redis的数据持久化_redis_02

开启子进程执行RDB,避免主进程受到影响

注:Redis停机时会执行一次RDB

Redis内部有触发RDB的机制

默认是1分钟内改了1万次,或5分钟内改了10次,或15分钟内改了1次。

Redis的数据持久化_数据_03

注意: 30s内12个key改变,触发快照,会将前10个key进行持久化,而后两个key重新从0s开始计算,如果达到30s,没有满足10个key改变的条件,那么不进行持久化操作

stop-writes-on-bgsave-error

当Redis无法写入磁盘的话,直接关掉Redis的写操作。默认yes

Redis的数据持久化_redis_04

注:在开启RDB且最近一次bgsave执行失败的情况下,如果该参数为yes,则Redis会阻止客户端的写入,直到bgsave执行成功。

rdbcompression 压缩文件

建议不开启压缩,会消耗cpu

Redis的数据持久化_redis_05

rdbchecksum 检查完整性

存储快照后,还可以让redis使用CRC64算法来进行数据校验

(但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能)

Redis的数据持久化_子进程_06

如何停止RDB

动态停止RDB:redis-cli config set save “”#save后给空值,表示禁用保存策略rdb文件

  • Fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等) 数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程
  • 在Linux程序中,fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,出于效率考虑,Linux中引入了“写时复制技术”
  • 一般情况父进程和子进程会共用同一段物理内存,只有进程空间的各段的内容要发生变化时,才会将父进程的内容复制一份给子进程 ​

Redis的数据持久化_子进程_07

​读时共享,写时复制​

RDB保存策略原理

bgdsave开始时会fork主进程得到子进程,子进程共享主进程的内存数据,完成fork后读取内存数据并写入

RDB的优缺点:
优点:

1. RDB是一个紧凑压缩的二进制文件,代表Redis在某个时间点上的数据快照,适合备份,全量复制等场景。

2. 加载RDB恢复数据远远快于AOF的方式。

缺点:

1.没办法做到实时持久化/秒级持久化,因为bgsave每次运行都要执行fork操作创建子进程,属于重量级操作,频繁执行成本过高。

2.最后一次持久化后的数据可能丢失

3.fork子进程,压缩,写出rdb文件都比较耗时

Redis的数据持久化_子进程_08

AOF持久化

AOF全称为Append Only File (追加文件)。Redis处理的每一个写命令都会记录在AOF文件,可以看做是命令日志文件。

注:只允许追加不允许改写的文件

AOF默认不开启,需要修改redis.conf配置文件来开启AOF

Redis的数据持久化_redis_09

appendfilename “appendonly.aof”:默认生成的文件名字:appendonly.aof

开启aof:appendonly yes

AOF的命令记录的频率也可以通过redis.conf文件来配:

Redis的数据持久化_子进程_10

# 表示每执行一次写命令,立即记录到AOF文件

 appendfsync always

# 写命令执行完先放入AOF缓存区,然后表示每隔1秒将缓存取数据写入AOF文件,是默认的方案

appendfsync everysec

# 写命令执行完先放入AOF缓冲区,由操作系统决定何时将缓存区内容写入磁盘

appendfsync no

配置项

刷盘时机

优点

缺点

Always

同步刷盘

可靠性高,几乎不丢数据

性能影响大

everysec

每秒刷盘

性能适中

最大丢失1秒数据

no

操作系统控制

性能最好

可靠性较差,可能丢失大量数据

因为是记录命令,AOF文件会比RDB文件大的多,而且AOF会记录对同一个key的多次写操作,但是自有最后一次操作才有意义,通过执行​​bgrewriteaof​​命令,可以将AOF文件执行重写功能,用最少的命令达到相同的效果。

Redis的数据持久化_子进程_11

Redis的数据持久化_子进程_12

重写原理,如何实现重写

AOF文件持续增长而过大时,会fork出一条新进程来将文件重写(也是先写临时文件最后再rename),redis4.0版本后的重写,是指上就是把rdb 的快照,以二级制的形式附在新的aof头部,作为已有的历史数据,替换掉原来的流水账操作

no-appendfsync-on-rewrite:

如果 no-appendfsync-on-rewrite=yes ,不写入aof文件只写入缓存,用户请求不会阻塞,但是在这段时间如果宕机会丢失这段时间的缓存数据。(降低数据安全性,提高性能)

如果 no-appendfsync-on-rewrite=no, 还是会把数据往磁盘里刷,但是遇到重写操作,可能会发生阻塞。(数据安全,但是性能降低)

触发机制,什么时候重写

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

重写虽然可以节约大量磁盘空间,减少恢复时间。但是每次重写还是有一定的负担的,因此设定Redis要满足一定条件才会进行重写

auto-aof-rewrite-percentage:设置重写的基准值,文件达到100%时开始重写(文件是原来重写后文件的2倍时触发)

auto-aof-rewrite-min-size:设置重写的基准值,最小文件64MB。达到这个值开始重写。

重写流程

(1)bgrewriteaof触发重写,判断是否当前有bgsave或bgrewriteaof在运行,如果有,则等待该命令结束后再继续执行

(2)主进程fork出子进程执行重写操作,保证主进程不会阻塞。

(3)子进程遍历redis内存中数据到临时文件,客户端的写请求同时写入aof_buf缓冲区和aof_rewrite_buf重写缓冲区保证原AOF文件完整以及新AOF文件生成期间的新的数据修改动作不会丢失。

(4)

     a.子进程写完新的AOF文件后,向主进程发信号,父进程更新统计信息。

     b.主进程把aof_rewrite_buf中的数据写入到新的AOF文件。

(5)使用新的AOF文件覆盖旧的AOF文件,完成AOF重写。

AOF的优缺点:
优点
  • 备份机制更稳健,丢失数据概率更低。
  • 可读的日志文本,通过操作AOF稳健,可以处理误操作。
缺点
  • 比起RDB占用更多的磁盘空间。
  • 恢复备份速度要慢。
  • 每次读写都同步的话,有一定的性能压力。
RDB与AOF对比

RDB

AOF

持久化方式

定时对整个内存做快照

记录每一次执行命令

数据完整性

不完整,两次备份之间会丢失

相对完整,取决于刷盘策略

文件大小

会压缩,文件体积小

记录命令,文件体积很大

宕机恢复时间

很快

数据恢复优先级

低,因为数据完整性不如AOF

高,因为数据完整性更高

系统资源占用

高,大量cpu和内存消耗

低,主要是磁盘IO资源但AOF重写时会占用大量的cpu和内存资源

使用场景

可以容忍数分钟的数据丢失,对求更快的启动速度

对数据安全性要求较高常见

Redis的数据持久化_数据_13