Redis持久化(RDB/AOF)

前文

本文是本人的第一篇博客,也是借鉴了很多技术大佬的博客和官网文档,博客的排版用的也不是很熟练,还望多多谅解。

写博客的目的很简单,也是为了督促自己更有效的学习,总结所学的知识点。如有不足,还请各位大佬多指教,希望借此得到进步,感谢!

 

目录

一、持久化目的

二、持久化分类

1.RDB持久化

1.1.概念

1.2.触发条件

1.3.执行日志

1.4.其他触发机制

1.5.执行流程

1.6.启动时加载

1.7.优缺点

2.AOF持久化

2.1.概念

2.2.开启

2.3.配置文件AOF相关其他参数设置

2.4.执行流程

2.5.启动时加载

2.6.AOF优缺点

三、参考资料


 

一、持久化目的


Redis是内存数据库,所有数据都是存储在内存中的,如果不定期将Redis中的数据库状态保存到磁盘,那么一旦服务器进程退出,就会导致数据的永久丢失。当下次Redis重启时,利用持久化文件实现数据恢复。除此之外,为了进行灾难备份,可以将持久化文件拷贝到一个远程位置。

 

二、持久化分类


Redis的持久化分为两种:

  1. RDB持久化(快照)
  2. AOF持久化(写命令)

 

1.RDB持久化

1.1.概念

又称快照持久化,是将当前进程汇总的数据生成快照保存到硬盘,保存的文件后缀名为rdb。

 

1.2.触发条件

  1. 手动触发
  2. 自动触发

 

1.2.1.手动触发

手动触发有两个命令save和bgsave

  • save命令:会阻塞服务器进程,直到快照文件创建完成为止。阻塞期间服务器不能处理任何命令要求
  • bgsave命令:新建子进程,用于生成rdb文件,与此同时,redis主进程继续处理请求,因此不会阻塞服务器进程(可以通过lastsave命令查看是否成功生成rdb文件)

1.2.2.自动触发

通过配置文件,能够设置redis自动触发bgsave;

save m n   当m秒内发生n次变化时,自动触发

save 900 1
save 300 10
save 60 10000

含义:
Redis 服务器在 900 秒之内,对数据库进行了至少一次修改
Redis 服务器在 300 秒之内,对数据库进行了至少 10 次修改
Redis 服务器在 60 秒之内,对数据库进行了至少 10000 次修改

若配置文件中有多条save命令时,只要满足任意一个,bgsave就会被执行

 

实现原理

Redis的save m n,是通过serverCron函数、dirty计数器、和lastsave时间戳来实现的。

serverCron是Redis服务器的周期性操作函数,默认每隔100ms执行一次;该函数对服务器的状态进行维护,其中一项工作就是检查 save m n 配置的条件是否满足,如果满足就执行bgsave。

dirty计数器是Redis服务器维持的一个状态,记录了上一次执行bgsave/save命令后,服务器状态进行了多少次修改(包括增删改);而当save/bgsave执行完成后,会将dirty重新置为0。

例如,如果Redis执行了set mykey helloworld,则dirty值会+1;如果执行了sadd myset v1 v2 v3,则dirty值会+3;注意dirty记录的是服务器进行了多少次修改,而不是客户端执行了多少修改数据的命令。

lastsave时间戳也是Redis服务器维持的一个状态,记录的是上一次成功执行save/bgsave的时间。

save m n的原理如下:每隔100ms,执行serverCron函数;在serverCron函数中,遍历save m n配置的保存条件,只要有一个条件满足,就进行bgsave。对于每一个save m n条件,只有下面两条同时满足时才算满足:

(1)当前时间-lastsave > m

(2)dirty >= n

 

配置文件rdb相关其他参数设置

stop-writes-on-bgsave-error    持久化过程中发生错误时是否继续处理Redis执行命令,默认不处理

rdbcompression                       是否压缩rdb文件,需要消耗一些CPU资源,默认不压缩

rdbchecksum                           保存rdb文件的时候,进行错误检查校验,在写入文件和读取文件时都起作用;

                                                关闭checksum在写 入文件和启动文件时大约能带来10%的性能提升,但是数据损坏时无法发现

dir ./                                          rdb文件保存的目录

dbfilename dump.rdb                rdb文件名

 

1.3.执行日志

下图是save m n触发bgsave执行时,服务器打印日志的情况:

 

1.4.其他触发机制

除了save m n以外,还有一些其他情况会触发bgsave:

  • 在主从复制场景下,如果从节点执行全量复制操作,则主节点会执行bgsave命令,并将rdb文件发送给从节点;

  • 执行shutdown命令时,自动执行rdb持久化,如下图所示:

 

1.5.执行流程

 

图片中的5个步骤所进行的操作如下:

  • Redis父进程首先判断:当前是否在执行save,或bgsave/bgrewriteaof的子进程,如果在执行则bgsave命令直接返回。bgsave/bgrewriteaof 的子进程不能同时执行,主要是基于性能方面的考虑:两个并发的子进程同时执行大量的磁盘写操作,可能引起严重的性能问题

  • 父进程执行fork操作创建子进程,这个过程中父进程是阻塞的,Redis不能执行来自客户端的任何命令

  • 父进程fork后,bgsave命令返回”Background saving started”信息并不再阻塞父进程,并可以响应其他命令

  • 子进程创建RDB文件,根据父进程内存快照生成临时快照文件,完成后对原有文件进行原子替换

  • 子进程发送信号给父进程表示完成,父进程更新统计信息

 

1.6.启动时加载

由于AOF的优先级更高,所以只有关闭AOF,才会在Redis服务器启动时检测RDB文件并自动加载。服务器载入RDB文件期间出于阻塞状态,直到载入完成为止

启动日志输出

Redis载入RDB文件时,会对RDB文件进行校验,如果文件损坏,则日志中会打印错误,Redis启动失败

 

1.7.优缺点

优点:

  1. 命令bgsave,fork子线程来创建RDB文件,不影响Redis主线程的日常任务处理
  2. 生成的RDB文件为压缩的二进制文件,方便传输和保存,同时方便将Redis数据库复原到某一时刻,起到备份作用,提高数据安全性
  3. 恢复大数据集的速度比AOF快

缺点:

  1. 无法做到实时持久化,bgsave每次执行都会fork子进程,属于重量级操作,频繁执行成本过高,影响性能
  2. 无法做到数据一致性,如果没有达到生成RDB文件的条件之前服务器奔溃了,那么这部分的数据会丢失

 

2.AOF持久化

2.1.概念

将Redis执行的每次写命令记录到单独的日志文件中,当Redis重启时再次执行AOF文件中的命令来恢复数据

 

2.2.开启

Redis服务器默认开启RDB,关闭AOF;要开启AOF,需要在config配置文件中设置

appendonly yes

 

2.3.配置文件AOF相关其他参数设置

appendonly                                       是否打开AOF持久化功能

appendfilename                                 AOF文件名称

dir ./                                                   AOF文件所在目录

no-appendfsync-on-rewrite no          AOF重写期间是否禁止fsync;如果开启该选项,可以减轻文件重写时CPU和硬盘的负载(尤其是硬盘),但是可能会丢失AOF重写期间的数据;需要在负载和安全性之间进行平衡

auto-aof-rewrite-percentage 100      文件重写触发条件之一

auto-aof-rewrite-min-size 64mb       文件重写触发提交之一

aof-load-truncated yes                     如果AOF文件结尾损坏,Redis启动时是否仍载入AOF文件

appendfsync                                    同步频率

同步策略有三种方式

  • always        redis执行每个写命令时,都同步写入硬盘,会严重降低redis性能
  • everysec     每秒执行一次,显示的在这一秒内执行的命令写入到硬盘。everysec是always与no策略的折中,是性能和数据安全性的平衡,因此是Redis的默认配置,也是我们推荐的配置
  • no               不同步到硬盘,让操作系统来决定何时进行同步,通常同步周期为30秒,由于文件同步时间不可控,并且缓冲区的堆积数据会很多,数据安全性无法保证

 

2.4.执行流程

AOF的执行流程包括:

  • 命令追加(append):将Redis的写命令追加到缓冲区aof_buf

  • 文件写入(write)和文件同步(sync):根据不同的同步策略将aof_buf中的内容同步到硬盘

  • 文件重写(rewrite):定期重写AOF文件,达到压缩的目的

当Redis启动AOF持久化后,会将所有写命令追加到缓冲区aof_buf中,此时还未写入到AOF文件,默认情况下只有当缓冲区被填满或超过指定时限后,才真正的同步到硬盘里。但这样会带来安全问题,所以会调用fsync函数,根据不同的同步策略强制操作系统立即将缓冲区中的数据写入AOF文件中,实现同步,从而确保数据安全性。

AOF文件默认就是不断追加,文件只会越来越大。过大的AOF文件也会导致数据恢复的时间越来越长。因此就有了文件重写。

文件重写是指定期重写或者说压缩AOF文件,减小文件大小。需要注意的是,AOF重写是把Redis进程内的数据转化为写命令,同步到新的AOF文件,不会对旧的AOF文件进行任何读取、写入操作。

重写方法:

  • 过期、无效的额数据或命令不再写入文件,例如重复设值或被删除的数据等

  • 合并多条命令。不过为了防止单条命令过大造成客户端缓冲区溢出,对于list、set、hash、zset类型的key,并不一定只使用一条命令;而是以某个常量为界将命令拆分为多条。这个常量在redis.h/REDIS_AOF_REWRITE_ITEMS_PER_CMD中定义,不可更改,3.0版本中值是64。

2.4.1.文件重写的触发

文件重写的触发分为两种:

  • 手动触发
  • 自动触发

 

手动触发

直接调用bgrewriteaof命令,该命令的执行与bgsave有些类似:都是fork子进程进行具体的工作,且都只有在fork时阻塞。

 

此时服务器执行日志如下:

 

自动触发

根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数,以及aof_current_size和aof_base_size状态确定触发时机。

  • auto-aof-rewrite-min-size:执行AOF重写时,文件的最小体积,默认值为64MB。

  • auto-aof-rewrite-percentage:执行AOF重写时,当前AOF大小(即aof_current_size)和上一次重写时AOF大小(aof_base_size)的比值。

 

其中,参数可以通过config get命令查看:

 

状态可以通过info persistence查看:

 

只有当auto-aof-rewrite-min-size和auto-aof-rewrite-percentage两个参数同时满足时,才会自动触发AOF重写,即bgrewriteaof操作。

 

自动触发bgrewriteaof时,可以看到服务器日志如下:

 

2.4.2.文件重写流程

 

 

关于文件重写的流程,有两点需要特别注意:

  • 重写由父进程fork子进程进行;

  • 重写期间Redis执行的写命令,需要追加到新的AOF文件中,为此Redis引入了aof_rewrite_buf缓存。

 

对照上图,文件重写的流程如下:

  • Redis父进程首先判断当前是否存在正在执行 bgsave/bgrewriteaof的子进程,如果存在则bgrewriteaof命令直接返回,如果存在bgsave命令则等bgsave执行完成后再执行。前面曾介绍过,这个主要是基于性能方面的考虑。

  • 父进程执行fork操作创建子进程,这个过程中父进程是阻塞的。

  • 父进程fork后,bgrewriteaof命令返回”Background append only file rewrite started”信息并不再阻塞父进程,并可以响应其他命令。Redis的所有写命令依然写入AOF缓冲区,并根据appendfsync策略同步到硬盘,保证原有AOF机制的正确。

    由于fork操作使用写时复制技术,子进程只能共享fork操作时的内存数据。由于父进程依然在响应命令,因此Redis使用AOF重写缓冲区(图中的aof_rewrite_buf)保存这部分数据,防止新AOF文件生成期间丢失这部分数据。也就是说,bgrewriteaof执行期间,Redis的写命令同时追加到aof_buf和aof_rewirte_buf两个缓冲区。

  • 子进程根据内存快照,按照命令合并规则写入到新的AOF文件。

  • 子进程写完新的AOF文件后,向父进程发信号,父进程更新统计信息,具体可以通过info persistence查看。

    父进程把AOF重写缓冲区的数据写入到新的AOF文件,这样就保证了新AOF文件所保存的数据库状态和服务器当前状态一致。

    使用新的AOF文件替换老文件,完成AOF重写。

 

2.5.启动时加载

当AOF开启时,Redis启动时会优先载入AOF文件来恢复数据;只有当AOF关闭时,才会载入RDB文件恢复数据。

 

当AOF开启,且AOF文件存在时,Redis启动日志:

 

当AOF开启,但AOF文件不存在时,即使RDB文件存在也不会加载(更早的一些版本可能会加载,但3.0不会),Redis启动日志如下:

 

文件校验

与载入RDB文件类似,Redis载入AOF文件时,会对AOF文件进行校验,如果文件损坏,则日志中会打印错误,Redis启动失败。但如果是AOF文件结尾不完整(机器突然宕机等容易导致文件尾部不完整),且aof-load-truncated参数开启,则日志中会输出警告,Redis忽略掉AOF文件的尾部,启动成功。aof-load-truncated参数默认是开启的:

 

 

2.6.AOF优缺点

优点:

  1. AOF文件可读性交强,也可手动操作写命令
  2. 支持秒级持久化、兼容性好
  3. 若AOF文件报错,比如在写AOF文件时redis崩溃了,redis提供了多种恢复AOF文件的方式,例如使用redis-check-aof工具修正AOF文件(一般都是最后一条写命令有问题,可以手动取出最后一条写命令)

缺点:

  1. AOF文件较大
  2. 因为AOF知识追加写命令,所以理论上RDB比AOF方式更加健壮
  3. 对性能影响大

 

三、参考资料


Redis高可用详解:持久化技术及方案选择(来源:DBAplus社群)

Redis持久化RDB和AOF (来源:COSCHINA)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值