Redis是基于内存的。持久化是指将数据从断电易失的内存中保存到永久存储的硬件设备(硬盘等)中。
Redis提供了2种持久化方式,
- RDB(Redis DB),类似于数据库的保存
- AOF(AppendOnlyFile),以日志文件形式保存
1. RDB
1.1 RDB介绍
RDB方式是通过快照(snapshotting)完成的,当符合一定条件时Redis会自动将内存中的数据进行快照并持久化到硬盘。在默认情况下,Redis 将数据库快照保存在名字为 dump.rdb的二进制文件中。redis.conf可以配置这些:
-
RDB执行规则
RDB执行规则
- RDB文件名字
-
RDB文件路径
名称路径
1.2 RDB执行过程
要想触发快照,生成RDB文件,有4种方式:
- 手动执行命令;sava 或bgsave
- 配置文件中的策略自动执行
- 执行flushall命令
- 执行主从复制操作
我们主要从1、2两种方式看一下执行过程,配置文件中的策略过程和bgsave是一样的。
1.2.1 save
客户端中执行save命令,这时会阻塞Redis服务,服务端执行命令时无法响应客户端其他请求,创建新的dump.rdb替代旧文件。
优点:操作简单
缺点:在持久化过程中,阻塞Redis服务,无法响应客户端请求。
适合停机维护,服务低谷时段
1.2.2 bgsave
客户端中执行bgsave命令,Redis服务不会阻塞,具体过程如下:
1. redis使用fork函数复制一份当前进程的副本(子进程)
2. 父进程继续接收并处理客户端发来的命令,而子进程开始将内存中的数据写入硬盘中的临时文件。
3. 当子进程写入完所有数据后会用该临时文件替换旧的RDB文件,至此,一次快照操作完成。

优点:持久化过程中也可提供服务
缺点:复杂度较高
适合线上执行
1.3 RDB注意事项
- Redis启动后会读取RDB快照文件,将数据从硬盘载入到内存
- 根据数据量大小与结构和服务器性能不同,这个时间也不同。通常将记录一千万个字符串类型键、大小为1GB的快照文件载入到内存中需要花费20~30秒钟
- bgsave执行快照时不会被阻塞,但是如果redis数据集比较大的时候,fork()过程可能比较耗时,造成服务器在一段时间内停止处理客户端的请求
- 假如父进程中有200G数据,foek()子进程并不会占用200G内存,子进程内存中存储父进程内存的指向
- redis在进行快照的过程中是生成临时文件,等快照结束后用临时文件将旧的RDB文件替换成新的,也就是说任何时候RDB文件都不会被修改
- RDB文件是经过压缩的二进制文件,占用的空间会小于内存中的数据,更加利于传输
1.4 RDB优缺点
- 缺点:使用RDB方式实现持久化,一旦Redis异常退出,就会丢失最后一次快照以后更改的所有数据。这个时候我们就需要根据具体的应用场景,通过组合设置自动快照条件的方式来将可能发生的数据损失控制在能够接受范围。如果数据相对来说比较重要,希望将损失降到最小,则可以使用AOF方式进行持久化
- 优点: RDB可以最大化Redis的性能:父进程在保存RDB文件时唯一要做的就是fork出一个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程无需执行任何磁盘I/O操作
2. AOF
2.1 AOF介绍
默认情况下Redis没有开启AOF(append only file)方式的持久化。开启AOF持久化后每执行一条会更改Redis中的数据的命令,Redis就会将该命令写入硬盘中的AOF文件,这一过程显然会降低Redis的性能,但大部分情况下这个影响是能够接受的,另外使用较快的硬盘可以提高AOF的性能。调整AOF持久化策略,可以在服务出现故障时,不丢失任何数据,也可以丢失一秒的数据。相对于RDB损失小得多。redis.conf中配置:

AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数设置的
2.2 AOF保存机制
AOF执行机制有2种,一是客户端执行fsync
或fdatasync
命令,一是根据配置文件中配置的appendfsync参数。配置文件中如下:

always的速度慢,everysec和no都很快
2.3 AOF重写机制
Redis中的操作经常会遇到这样的指令:

很明显,第一组就等于
set age 20
,第二组就等于sadd likes apple banana money
。由于AOF文件会很大,就要合并重复的操作,AOF会使用尽可能少的命令来记录,这就需要重写。重写基于写时复制的,直接将内存的数据反转为命令。
AOF重写出发有2种,一是手动命令:
bgrewriteaof
;一是根据配置文件中的配置自动执行bgrewriteaof
命令。
重写过程
- 父进程执行fork创建子进程,开销等同于bgsave过程。主进程fork操作完成后,继续响应其他命令。所有修改命令依然写入AOF缓冲区,并根据appendfsync策略同步到磁盘,保证原有AOF机制正确性。
- 由于fork操作运用写时复制技术,子进程只能共享fork操作时的内存数据。由于父进程依然响应命令,redis使用“AOF重写缓冲区”保存这部分新数据,防止新AOF文件生成期间丢失这部分数据。
- 子进程根据内存快照,按照命令合并规则写入到新AOF文件。每次批量写入硬盘数据量由
aof-rewrite-incremental-fsync
控制,默认是32MB,防止单次刷盘数据过多造成硬盘阻塞。 - 新AOF文件写入完成后,子进程发送信号给父进程,父进程更新统计信息。同时父进程把AOF重写缓冲区数据写入到新的AOF文件。
-
使用新AOF文件替换老文件,完成AOF重写。
注:如果写入操作的时候出现故障导致命令写半截,可以使用redis-check-aof工具修复
重写流程
2.4 AOF优缺点
- 优点
- 写入机制,默认fysnc每秒执行,性能很好不阻塞服务,最多丢失一秒的数据
- 重写机制,优化AOF文件
- 如果误操作了(FLUSHALL等),只要AOF未被重写,停止服务移除AOF文件尾部FLUSHALL命令,重启Redis,可以将数据集恢复到 FLUSHALL 执行之前的状态
- 缺点
- 相同数据集,AOF文件体积较RDB大了很多
- 恢复数据库速度比RDB慢(文本,命令重演)
3. RDB、AOF
- 一般来说,如果对数据的安全性要求非常高的话,应该同时使用两种持久化功能。
- 如果可以承受数分钟以内的数据丢失,那么可以只使用 RDB 持久化。
- 并不推荐只使用 AOF 持久化这种方式。 因为定时生成 RDB 快照(snapshot)非常便于进行数据库备份, 并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快 。
- 如果RDB、AOF同时使用的话, 那么Redis重启时,会优先使用AOF文件来还原数据
网友评论