Redis持久化

目录

RDB持久化

1.什么是 RDB 持久化

2.写时复制

3.RDB优缺点

AOF持久化

1.什么是AOF持久化

2.AOF的执行流程

3.三种写回策略

4.AOF重写

5.AOF优缺点


使用Redis缓存的时候,我们经常需要对内存中的数据进行持久化,也就是将内存中的数据写入到硬盘中。大部分原因是为了之后重用数据(比如重启机器、机器故障之后恢复数据),或者是为了做数据同步(比如 Redis 集群的主从节点通过 RDB 文件同步数据)。

RDB持久化

1.什么是 RDB 持久化

RDB持久化又称为RDB快照,所谓快照,就是某一时刻的数据拷贝。

RDB快照是全量快照,也就是把内存中的「所有数据」都记录到磁盘中。RDB,就是一份全量数据文件,恢复的时候,直接加载到内存中即可,所以RDB数据恢复速度很快。

Redis 提供了两个命令来生成 RDB 快照文件,分别是 save 和 bgsave,他们的区别就在于是否在「主线程」里执行:

  • save : 同步保存操作,会阻塞 Redis 主线程;
  • bgsave : fork 出一个子进程,子进程执行,不会阻塞 Redis 主线程,默认选项。

快照持久化是 Redis 默认采用的持久化方式,可以通过配置文件的选项来实现每隔一段时间自动执行一次 bgsave 命令,在 redis.conf 配置文件中默认有此下配置

save 900 1
save 300 10
save 60 10000

 这里的save其实是指bgsave命令,以第一行配置为例,表示如果900秒内至少有1个key被修改就执行bgsave。

2.写时复制

前文提到,执行 bgsave 过程中,由于是交给子进程来构建 RDB 文件,那么主进程是否能够对数据进行修改呢?

答案是可以的,这里就用到了写时复制技术(Copy-on-write)。

执行 bgsave 命令的时候,会通过 fork() 一个子进程,此时子进程和父进程是共享同一片内存数据的,创建子进程的时候,会复制父进程的页表,但是页表指向的实际物理内存是同一个,操作系统会把这一块内存空间标记为只读(read-only)。只有当内存数据被修改时(写操作),才会真正拷贝物理内存,这就是写时复制。

写时复制的好处在于减少创建子进程时的性能损耗,子进程创建时只需要复制页表而不是进行物理内存的拷贝,加快了子进程的创建速度。

3.RDB优缺点

优点:

  • RDB是一个紧凑压缩的二进制文件,代表Redis在某一个时间点上的数据快照,非常适合用于备份、全量复制等场景。
  • RDB是Redis数据的内存快照,数据恢复速度较快,相比于AOF的命令重放有着更高的性能。

缺点:

  • RDB方式无法做到实时或秒级持久化。因为持久化过程是通过fork子进程后由子进程完成的,子进程的内存只是在fork操作那一时刻父进程的数据快照。而fork操作是一个耗时操作,无法做到实时性。
  • RDB持久化过程中的fork操作,会导致内存占用加倍,而且父进程数据越多,fork过程越长。
  • RDB文件有文件格式要求,不同版本的Redis会对文件格式进行调整,存在老版本无法兼容新版本的问题。

AOF持久化

1.什么是AOF持久化

AOF(Append Only File) 持久化功能,是指保存写操作命令到日志的持久化方式,注意只有写操作命令,因为记录读操作对于持久化而言没有意义。

默认情况下 Redis 没有开启 AOF(append only file)方式的持久化,可以通过 appendonly 参数开启:

//redis.conf
appendonly yes

2.AOF的执行流程

1.命令追加(append):所有的写命令会追加到 AOF 缓冲区中。

2.文件写入(write):将 AOF 缓冲区的数据写入到 AOF 文件中。这一步需要调用write函数(系统调用),write将数据写入到了系统内核缓冲区之后直接返回了(延迟写),此时并没有同步到磁盘。

3.文件同步(fsync):AOF 缓冲区根据对应的写回策略向硬盘做同步操作。这一步需要调用 fsync 函数(系统调用), fsync 针对单个文件操作,对其进行强制硬盘同步,fsync 将阻塞直到写入磁盘完成后返回,保证了数据持久化。

4.文件重写(rewrite):随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的。

5.重启加载(load):当 Redis 重启时,可以加载 AOF 文件进行数据恢复。

3.三种写回策略

 redis.conf配置文件中的 appendfsync 配置项可以有以下 3 种参数可填:

  • Always 每次写操作命令执行完后,同步将 AOF 日志数据写回硬盘;
  • Everysec 每次写操作命令执行完后,先将命令写入到 AOF 文件的内核缓冲区,然后每隔一秒将缓冲区里的内容写回到硬盘;
  • No 不由 Redis 控制写回硬盘的时机,转交给操作系统控制写回的时机,也就是每次写操作命令执行完后,先将命令写入到 AOF 文件的内核缓冲区,再由操作系统决定何时将缓冲区内容写回硬盘。

3种写回策略本质上是在控制 fsync() 函数的调用时机,对于Always,在每次写入内核缓冲区(Page Cache)后,立刻调用fsync() ,而Everysec是创建一个异步任务来执行 fsync() 函数,No就是不主动调用fsync() 函数,让操作系统决定。

这 3 种写回策略都无法能完美解决「主进程阻塞」和「减少数据丢失」的问题,原因如下:

  • Always 策略的话,可以最大程度保证数据不丢失,但是由于它每执行一条写操作命令就同步将 AOF 内容写回硬盘,所以是不可避免会影响主进程的性能;
  • No 策略的话,是交由操作系统来决定何时将 AOF 日志内容写回硬盘,相比于 Always 策略性能较好,但是操作系统写回硬盘的时机是不可预知的,如果 AOF 日志内容没有写回硬盘,一旦服务器宕机,就会丢失不定数量的数据。
  • Everysec 策略的话,是上述两种方式的折中,避免了 Always 策略的性能开销,也比 No 策略更能避免数据丢失,当然如果上一秒的写操作命令日志没有写回到硬盘,发生了宕机,这一秒内的数据自然也会丢失。

4.AOF重写

由于AOF记录写操作命令,随着写操作命令增多,AOF文件会越来越大,当 AOF文件 变得太大时,Redis 能够在后台自动重写 AOF 产生一个新的 AOF 文件,这个新的 AOF 文件和原有的 AOF 文件所保存的数据库状态一样,但体积更小。

AOF 重写机制是在重写时,读取当前数据库中的所有键值对,然后将每一个键值对用一条命令记录到「新的 AOF 文件」,等到全部记录完后,就将新的 AOF 文件替换掉现有的 AOF 文件。

例如原来AOF文件保存有"set key breeze"和"set key yes"两个命令,执行重写后原有的第一个命令就没有必要记录了,只要根据对于key的新值来记录命令即可。

为了避免对 Redis 正常处理命令请求造成影响,Redis 将 AOF 重写程序放到子进程里执行。这里AOF后台重写也采用了写时复制copy-on-write,和RDB类似。

5.AOF优缺点

优点:

  • 数据丢失较少,数据安全性相对较高。根据使用的fsync策略(fsync是同步内存中redis所有已经修改的文件到存储设备),默认是appendfsync everysec,即每秒执行一次fsync,在这种配置下,redis仍然可以保持良好的性能,并且就算发生故障停机,最多指挥丢失一秒钟的数据(fsync会在后台线程执行,所以主线程可以继续努力的处理命令请求)
  • redis可以在aof文件体积变得过大时,自动的在后台对aof进行重写,重写后的新aof文件包含了恢复当前数据集所需要的最小命令集合。整个重写操作时绝对的,因此redis在创建新aof文件的过程中,append模式不断的将修改数据追加到现有的aof文件里面,即使重写过程中发生停机,现有的aof文件也不会丢失。而一旦新aof文件创建完毕,redis就会从旧aof文件切换到新aof文件,并开始对新aof文件进行追加操作。

缺点:

  • 由于会记录重复写操作命令,aof文件的大小往往要大于rdb格式的文件
  • aof在恢复大数据集时的速度比rdb的恢复速度要慢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值