Redis的持久化简述
持久化
- Redis支持数据的持久化,主要分为两种方式,分别是RDB和AOF。并且支持这两种的混合模式
- Redis是"先写内存后刷盘"类型的数据库,即Redis先执行命令,把数据先写入内存,然后才记录日志文件
RDB模式
简述
- Redis DataBase(快照/内存快照,缩写RDB)
- RDB持久化是把当前进程数据生成快照保存到磁盘上的过程,由于是某一时刻的快照,那么快照中的值要早于或者等于内存中的值
相关配置
#自动触发持久化
save <seconds> <changes>
#开启RDB,如果配置的save "",则是关闭RDB
save m n
#RDB文件名称
dbfilename dump.rdb
#文件保存路径
dir /data/redis/data/
#是否压缩,Redis官方的建议是请保持该选项设置为yes
rdbcompression yes
#导入时是否检查,这个功能大概会多损失10%左右的性能,但获得了更高的数据可靠性。
#如果您的Redis服务需要追求极致的性能,就可以将这个选项设置为no
rdbchecksum yes
触发方式
自动触发
- redis.conf中配置save m n。即在m秒内有n次修改时,自动触发bgsave生成rdb文件
- 主从复制时,从节点要从主节点进行全量复制时,也会触发bgsave操作,生成当时的快照发送到从节点
- 执行debug reload命令重新加载redis时也会触发bgsave操作
- 默认情况下执行shutdown命令时,如果没有开启aof持久化,那么也会触发bgsave操作
手动触发
- 通过调用save、bgsave命令进行
相关命令
- save
- 阻塞当前Redis服务器,直到RDB过程完成为止,对于内存 比较大的实例会造成长时间阻塞,线上环境不建议使用
- bgsave
- Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短
持久化流程
- 主进程fork一个子进程,并与子进程共享此时的内存快照(fork之后主进程上的修改对子进程不可见)
- 子进程开始将内存快照写入dump.rdb文件中
- 在fork子进程后,主进程修改了任何数据,同时会将该数据拷贝一个副本,之后交给子进程一并写入dump.rdb文件中。即copy-on-write
- 将dump.rdb文件替换旧的文件,并完成持久化
刷盘(持久化)注意事项
- 避免频繁的执行全量快照
- 频繁将全量数据写入磁盘,会给磁盘IO带来很大压力,多个快照竞争有限的磁盘带宽,前一个快照还没有做完,后一个又开始做了,容易造成恶性循环
- 容易造成主线程阻塞,在for子进程的时候会阻塞主线程
优缺点分析
- 优点
- RDB文件是某个时间节点的快照,默认使用LZF算法进行压缩,压缩后的文件体积远远小于内存大小,适用于备份、全量复制等场景
- Redis加载RDB文件恢复数据要远远快于AOF方式
- 缺点
- RDB方式实时性不够,无法做到秒级的持久化
- 每次调用bgsave都需要fork子进程,fork子进程属于重量级操作,频繁执行成本较高
- RDB文件是二进制的,没有可读性,AOF文件在了解其结构的情况下可以手动修改或者补全
- 数据持久化一致性处理方式(Copy-on-Write)
- 读取数据写入快照
- 更新的数据复制该数据的副本,当写入快照完成之后,再将副本数据写入快照
AOF模式
简述
- AOF(Append Only File),通过追加的方式记录的Redis执行成功的写入命令,以文本形式保存的日志,是可读的
- 是写后日志。即命令执行成功之后,再将该命令记录到日志中
- 当开启了AOF之久化功能时,每当执行成功的写入命令后,会以协议格式将执行的命令追加到AOF_Buffer缓冲区,并通过指定的刷盘策略进行持久化
- 以追加的形式记录日志,需要指定日志文件的重写方式来限制日志文件的大小
相关配置
#开启AOF持久化,默认情况下AOF功能是关闭的
appendonly no
#AOF持久化的文件名
appendfilename "appendonly.aof"
#同步策略
appendfsync everysec
#aof重写期间是否同步
no-appendfsync-on-rewrite no
#如果当前AOF文件的大小超过了,上次重写后AOF文件的百分之n后,就再次开始重写AOF文件
auto-aof-rewrite-percentage 100
#启动AOF文件重写操作的AOF文件最小大小。如果AOF文件大小低于这个值,则不会触发重写操作,默认为64MB
auto-aof-rewrite-min-size 64mb
#加载aof出错如何处理
aof-load-truncated yes
#文件重写策略
aof-rewrite-incremental-fsync yes
刷盘策略
- Always(同步写回)
- 每个写命令执行完,同时将命令写入到AofBuffer,然后将日志刷入磁盘
- 繁调刷盘,可能导致I/O卡顿的现象频繁
- Everysec(每秒写回)
- 每个写命令执行完,同时将命令写入到AofBuffer,然后每隔一秒把缓冲区中的内容写入磁盘
- 建议使用everysec,出现故障时最多丢失1秒的数据
- No(操作系统控制的写回)
- 每个写命令执行完,同时写入到AofBuffer,由操作系统决定何时将缓冲区内容写回磁盘
为什么采用写后日志
- 避免额外的检查开销
- 不会阻塞当前的写操作
- 如果命令执行完成,写日志之前宕机了,会丢失数据
- 主线程写磁盘压力大,导致写盘慢,阻塞后续操作
重写流程
主进程fork子进程(bgRewriteAof)后
- 主进程
- 继续处理新的写入命令,并记录到两个(旧、新)日志文件Aof_Buffer缓冲区
- 将执行成功的命令写入到旧的AOF日志文件中
- 子进程
- 把数据转为写指令存入新的AOF文件。(记录的是每个数据的最后一次写指令,也就是最新的数据,不会记录之前冗余的操作,可以很大程度的缩小AOF的体量)
- 将Aof_buffer缓冲区的日志写入AOF文件
- 将新的AOF文件替换旧的AOF文件
- 完成重写
混合模式(4.0版本增加)
Redis 4.0 中提出了一个混合使用 AOF 日志和RDB快照的方法。简单来说,RDB快照以一定的频率执行,在两次快照之间,使用 AOF 日志记录这期间的所有命令操作