【redis系列】(四)数据的持久化

本文介绍了Redis的两种持久化方式——RDB和AOF,详细解释了它们的工作原理、优缺点及如何选择合适的持久化方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

我们都知道redis的数据都是存储在内存中,而存储在内存中的一大弊端就是断电易失。

所以对redis中的数据进行持久化存储是非常必要的,本文主要介绍一个redis持久化的两种方式——RDBAOF

持久化的问题

在详细介绍RDB和AOF的理论之前,我们先来想象一个持久化的问题。

比如某个redis节点在8:00需要备份数据,假设每次备份需要30分钟,那么这个节点有两个状态可以选择——阻塞或者非阻塞。

阻塞状态下,整个节点将在30分钟内不能对外提供服务,违背了高可用的原则,这无疑不是我们想要的状态。

非阻塞状态下又有下面这个问题需要考虑:

当redis在8:00的时候开始向硬盘刷写数据,但是这半个小时之间如果redis中的数据发生了改变怎么办?

如果将改变后的数据继续向硬盘中刷写,那这数据算是8点的数据呢还是8点半的数据呢?

所以在非阻塞的情况下进行数据备份就会造成数据时点混乱的问题。

带着这个问题,我们再来介绍RDB和AOF。

RDB

这种持久化的方式又叫快照(snapshotting)。

在默认情况下,redis会将数据库快照保存在名为dump.rdb的二进制文件中。

工作方式

当redis需要保存dump.rbd文件时,服务器会执行以下操作:

  1. redis调用forks(),同时拥有父进程和子进程。

  2. 子进程将数据集写入一个临时的RDB文件中。

  3. 当子进程完成了对新RDB文件的写入后,redis会用新RDB文件代替原有的RDB文件,并将其删除。

工作原理

通过上面介绍的RDB的工作方式,会发现最核心的一步是redis调用forks。

那么我们就来说说这个forks。

不过在介绍forks之前,我们先来说说linux中的进程隔离

所谓进程隔离,就是指进程中的变量在其他进程中访问不到,除非本进程主动将该变量export出去。

forks的作用是在当前进程的基础上创造出一个子进程,子进程中包含了父进程中的所有变量的副本

由于进程之间的隔离性,所以父进程对变量的更改,子进程是感知不到的,反之亦然。

这种特性就把rdb备份的时点问题解决了。

在要备份的时间节点创建出一个子进程,这个子进程包含与当前进程完全一样的变量,但是对变量的改变又相互独立。

也就是说,子进程中的变量都是fork出来的时间节点的状态,父进程则可以继续对外提供服务,接收变量的改变操作。

需要注意一点的是,fork出来的子进程与父进程之间存在一个copy-on-write的机制。

这个机制是说,当子进程刚刚被fork出来的时候,为了节省内存,与父进程是共享同一块内存区域的。

但是父进程中的某块数据发生改变后,就会另外开辟一块内存存放新数据,老数据接着被子进程持有。

优缺点

优点

RBD是一个非常紧凑的文件,保存了某个时间点的数据集,非常适用于数据集的备份,并且可以很方便的传送到远端的数据中心,很适合灾备。

RBD在保存的时候父进程唯一需要做的就是fork出一个子进程,剩下的工作都由子进程来做。这种方式可以最大化redis的性能。

与AOF相比,RDB在恢复大数据集的时候会更快一些。

缺点

redis要完整的保存整个数据集是个很繁重的工作,每次保存都要花费不短的时间。如果这段时间内发生了宕机,未被保存的数据就找不回来了。

当数据集很大的时候,fork也是很消耗时间的。

AOF

由于RDB的方式太“重”了,每次都需要把全量数据进行备份,这样每次备份的时间都会很长,万一在备份期间发生故障就会导致数据的永久丢失。

为了解决这个问题,1.1版本后提出了AOF的解决方案。

所谓AOF,全称就是Append-only File

可以通过在配置文件中打开AOF:

appendonly yes

当打开AOF之后,每当redis执行了一个改变了数据集的操作后,这个命令就会追加到AOF文件的末尾。

之后当redis重新启动之后,程序可以通过执行AOF文件中的命令来达到重建数据集的目的。

文件重写

我们都知道了AOF的工作方式是记录下来所有更改数据集的命令,所以随着redis的执行这个文件会变得越来越大。

但是很多情况下命令之间是可以进行合并的,比如对某个key自增了100次,在AOF文件中就会有100条对应的命令,这些命令是可以合并成1条的。

为了处理这种情况,redis增加了一个有趣的特性:在不打断服务端的情况下,对AOF文件进行重建——

执行BGREWRITEAOF命令,redis将生成一个新的AOF文件,这个文件包含了重建当前数据集所需的最少命令。

重写原理

AOF重写与RDB创建快照一样,都巧妙地利用了写时复制机制:

  1. redis执行fork命令,同时拥有父子进程。

  2. 子进程将新AOF文件写入临时文件。

  3. 对于新执行的写入命令,父进程一边将它们累积到一个内存缓存中,一边将这些改动追加到现有的AOF文件末尾。这样即使在重写的中途发生宕机,现有的AOF文件也是可靠的。

  4. 当子进程完成重写任务后,给父进程发一个信号,父进程将内存缓存中累积的所有命令追加到新AOF文件的末尾。

  5. redis原子地用新文件代替老文件,之后所有的命令都追加到新AOF文件的末尾。

AOF的时效性

redis将AOF刷写回硬盘的频率是可以配置的,主要有下面三种模式:

  1. 每次有新命令添加进AOF文件时都回写进硬盘。

  2. 每秒刷写一次。

  3. 交给系统来决定什么时候刷写。

推荐(并且是默认)使用第二种,这种策略可以兼顾安全性和速度,要丢失也仅仅丢失一秒内的数据。

优缺点

优点

可靠性: AOF每秒将文件刷写回硬盘的配置会保证即使丢失也只丢失1秒内的数据,相比较RDB模式可靠性大幅度提高。

对内存友好:当AOF文件变得过大的时候在后台对文件进行重写,重写后的AOF文件包含了恢复当前数据集的最少命令集合,整个重写过程是绝对安全的。

可读性:AOF文件包含了所有写入操作,并且以redis协议的格式保存,因此AOF文件的内容很容易被人读懂,对文件进行分析也很轻松。

缺点

文件体积大:对相同的数据集来说,AOF文件的体积要比RDB文件要大。

数据集恢复速度不如RDB快。因为通过AOF恢复数据集要将所有的命令执行一遍。

选择哪种持久化方式?

一般来说,同时采用两种持久化方式可以达到最佳效果。

定时生成RDB快照非常便于进行数据库备份,RDB恢复数据集的速度比AOF快。

所以综合AOF与RDB的优点,应该整合两种持久化方式一同使用。

在redis4.0后,AOF文件中也包括了RDB全量。

总结

本文介绍了两种redis的持久化方式——RDB和AOF。

介绍了它们的工作原理以及优缺点,最后介绍了理想的持久化方案是怎样的——统合使用RDB与AOF。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值