Redis学习[3] ——持久化

四. Redis 持久化

4.1 Redis 如何保证数据不丢失?

由于Redis的数据是保存在内存中,而内存中的数据会在Redis重启后丢失。因此,为了保证数据不丢失,Redis实现了数据持久化的机制。这个机制会将内存中的数据存储到磁盘,重启后可以从磁盘中恢复。

Redis共有三种数据持久化的方式:

  • AOF日志:每执行一条写操作命令,就把该命令以追加的方式写到一个文件里;
  • RDB快照:将某一时刻的内存数据,以二进制的方式写入磁盘;
  • 混合持久化方式:Redis 4.0新增,集成了AOF和RBD的优点。

4.2 AOF 日志是如何实现的?

4.2.1 AOF 日志写入

Redis在执行完一条写操作命令后,就会把该命令以追加写的方式写到一个文件中。当Redis重启后,会读取该文件记录的命令,逐个执行来恢复数据。

请添加图片描述

为什么是先执行命令,然后再把命令写入日志?

Reids 是先执行写操作命令后,才将该命令记录到 AOF 日志里的,这么做其实有两个好处:

  • 避免额外的检查开销:如果先写入再执行,那在写入的时候还无法确定是否能够执行。需要增加一步检查命令。
  • 不会阻塞当前写操作命令的执行:因为是完成写操作再去写入之日。

也会存在风险:

  • 数据可能会丢失:如果完成了写操作但还没来得及写入日志,服务器宕机了,会丢失这个数据;
  • 可能阻塞其他操作:AOF日志也是在主线程中执行的,会阻塞后续的操作等待写入完成;
4.2.2 AOF 日志写回策略

Redis写入AOF日志的过程可以由下图所示:

  1. Redis执行完写操作命令后,会将命令追加到一个缓冲区;
  2. 然后通过write()系统调用,将该缓冲区的命令写入到磁盘中的AOF文件中。实际上这一步只会让命令拷贝到了AOF文件的内核缓冲区,什么时候写入到硬盘由内核决定

Redis提供了3种写回硬盘的策略,控制什么时候将数据写入硬盘

  • Always:每次写操作执行完成后,直接将AOF日志数据写回硬盘;
  • Everysec:写操作执行完成后,数据会先存放在AOF文件的内核缓冲区,每隔一秒将缓冲区的内容写回到磁盘。
  • No:Redis不控制写回的执行,完全交给操作系统来控制

在这里插入图片描述

4.2.3 AOF 重写机制

随着执行的写操作越来越多,AOF日志文件会越来越大,在数据恢复时会越慢,影响性能。因此,Redis提供了重写机制,来避免AOF日志文件越写越大

AOF重写机制是根据K-V数据中的键值对,将每个键值对形成一个命令,记录到「新的 AOF 文件」中,完成后用这个「新的 AOF 文件」替换掉原有的AOF文件。

在这里插入图片描述

AOF重写机制的本质就是**只保留最新的在使用重写机制后,就会读取 name 最新的 value(键值对) ,然后用一条 「set name xiaolincoding」命令记录到新的 AOF 文件,之前的第一个命令就没有必要记录了,因为它属于「历史」命令,没有作用了。这样一来,一个键值对在重写日志中只用一条命令就行了**。

AOF重写是怎么完成的?

Redis是在每次需要AOF重写时,通过**新开辟一个子进程bgrewriteaof来完成AOF重写 **。这是由于:

  • 不会阻塞主进程,主进程可以继续处理命令请求;
  • 如果是多线程,由于共享数据,需要通过锁机制来保证数据安全,会影响性能。而子进程是拷贝数据的副本,创建子进程时,父子进程是共享内存数据的,不过这个共享的内存只能以只读的方式,而当父子进程任意一方修改了该共享内存,就会发生**「写时复制」,于是父子进程就有了独立的数据副本**,就不用加锁来保证数据安全

数据不一致问题?

因为在重写过程中,主进程仍然可以正常处理命令。如果发生了对已有key-value的修改,由于**「写时复制」子进程中关于这个key-value和主进程中的数据出现了不一致。为了解决这个问题,Redis设置了一个AOF重写缓冲区**。

在重写AOF期间,主进程对于所有的写操作命令除了将其加入到**「AOF 缓冲区」,还会加入到「AOF重写缓冲区」。当子进程完成重写时,会向主进程发送一个信号**(进程间的通信方式),主进程收到信号时会执行:

  • 将**「AOF重写缓冲区」中的所有内容追加到「新的 AOF 文件」**中;
  • 用**「新的 AOF 文件」**覆盖掉「旧的 AOF 文件」

截止到此,就完成了整个AOF重写的工作。

4.3 RDB 快照是如何实现的?

Redis使用AOF进行恢复时,如果AOF日志较多,需要逐个执行,势必会使Redis的恢复缓慢。为了解决这个问题,Redis增加了RDB快照。

RDB快照就是记录某一个瞬间的内存数据(是数据而不是命令),由于是直接记录的数据,因此在恢复时不需要执行操作命令,只需要将RDB文件读入内存即可,效率很高

4.3.1 RDB快照生成方法

Redis提供了两个命令来生成RDB快照:savebgsave,它们的区别在于生成快照是否在「主进程」里执行

  • save命令:在主进程中生成RDB快照,如果写入时间太长,会导致主线程阻塞,影响性能;
  • bgsave命令:会创建一个**子进程来生成RDB快照**,避免主线程的阻塞。

Redis 的快照是全量快照,也就是说每次执行快照,都是把内存中的**「所有数据」都记录到磁盘中。所以执行快照是一个比较重的操作,如果频率太频繁,可能会对 Redis 性能产生影响。如果频率太低,服务器故障时,丢失的数据会更多。**

4.3.2 RDB快照如何保证数据一致性?

如果是使用bgsave命令来执行生成快照,此时主进程仍然可以继续处理操作,但是由于快照是在一瞬间的数据,所以不需要去关注是否数据发生了变化。因此,RDB快照不存在数据一致性问题

如果主线程执行写操作,则被修改的数据会复制一份副本,然后 bgsave 子进程会**把原来副本数据写入 RDB 文件(不去管新的),在这个过程中,主线程仍然可以直接修改原来的数据。因此,借助写时复制技术(Copy-On-Write, COW)**,RDB不用关注数据一致性问题。

4.3 为什么会有混合持久化?

😊 RDB 优点是数据恢复速度快,但是快照的频率不好把握。频率太低,丢失的数据就会比较多,频率太高,就会影响性能。

😊 AOF 优点是丢失数据少,但是数据恢复不快。

为了集成了两者的优点, Redis 4.0 提出了混合使用 AOF 日志和RDB快照,也叫混合持久化,既保证了 Redis 重启速度,又降低数据丢失风险。

混合持久化是如何实现的?

  • 使用了混合持久化,AOF 文件的前半部分是 RDB 格式的全量数据,后半部分是 AOF 格式的增量数据

    当开启了混合持久化,在AOF重写日志时,重写子进程就不是把数据转换成命令写入了,而是**直接生成当时数据库的RDB快照并写入到AOF文件中。然后,主进程中记录在AOF重写缓冲区的命令继续以AOF日志的格式写入到AOF日志文件中**,替换旧的的 AOF 文件。

在这里插入图片描述

混合持久化优点:

  • 混合持久化结合了 RDB 和 AOF 持久化的优点,开头为 RDB 的格式,使得 Redis 可以更快的启动,同时结合 AOF 的优点,有减低了大量数据丢失的风险

混合持久化缺点:

  • AOF 文件中添加了 RDB 格式的内容,使得 AOF 文件的可读性变得很差
  • 兼容性差,如果开启混合持久化,那么此混合持久化 AOF 文件,就不能用在 Redis 4.0 之前版本了

资料参考

内容大多参考自:图解Redis介绍 | 小林coding (xiaolincoding.com)

  • 25
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值