文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Redis宕机了,Redis如何避免数据丢失?

2024-11-30 06:42

关注

解决这个问题的一个显而易见的方法是从后端数据库中恢复这些数据。然而,这种方法存在两个问题:首先,频繁访问数据库会给数据库带来巨大的压力;其次,这些数据是从较慢的数据库中读取出来的,性能肯定不如从Redis中读取,这会导致使用这些数据的应用程序响应速度变慢。因此,对于Redis来说,实现数据持久化以避免从后端数据库进行恢复是至关重要的。

目前,Redis实现数据持久化主要依靠两种机制,即AOF(Append-Only File)日志和RDB快照。在接下来的两个部分,我们将分别深入探讨这两种机制。首先,让我们重点关注AOF日志。

AOF 日志是如何实现的?

说到日志,我们比较熟悉的是数据库的写前日志(Write Ahead Log, WAL),也就是说,在实际写数据前,先把修改的数据记到日志文件中,以便故障时进行恢复。不过,AOF 日志正好相反,它是写后日志,“写后”的意思是 Redis 是先执行命令,把数据写入内存,然后才记录日志,如下图所示:

Redis AOF操作过程

那 AOF 为什么要先执行命令再记日志呢?要回答这个问题,我们要先知道 AOF 里记录了什么内容。

传统数据库的日志,例如 redo log(重做日志),记录的是修改后的数据,而 AOF 里记录的是 Redis 收到的每一条命令,这些命令是以文本形式保存的。

我们以 Redis 收到“set testkey testvalue”命令后记录的日志为例,看看 AOF 日志的内容。其中,“*3”表示当前命令有三个部分,每部分都是由“$+数字”开头,后面紧跟着具体的命令、键或值。这里,“数字”表示这部分中的命令、键或值一共有多少字节。例如,“$3 set”表示这部分有 3 个字节,也就是“set”命令。

Redis AOF日志内容

但是,为了避免额外的检查开销,Redis 在向 AOF 里面记录日志的时候,并不会先去对这些命令进行语法检查。所以,如果先记日志再执行命令的话,日志中就有可能记录了错误的命令,Redis 在使用日志恢复数据时,就可能会出错。

而写后日志这种方式,就是先让系统执行命令,只有命令能执行成功,才会被记录到日志中,否则,系统就会直接向客户端报错。所以,Redis 使用写后日志这一方式的一大好处是,可以避免出现记录错误命令的情况。

除此之外,AOF 还有一个好处:它是在命令执行后才记录日志,所以不会阻塞当前的写操作。

不过,AOF 也有两个潜在的风险。

首先,考虑一种情况:如果刚刚执行完一个命令,还来不及将该命令记录到日志中,Redis服务器突然宕机,那么这个命令以及相关数据可能会丢失。当Redis被用作缓存时,数据可以从后端数据库重新加载以进行恢复。但是,如果Redis被直接用作数据库,由于命令尚未被记录到日志中,因此无法使用日志进行数据恢复。

其次,尽管AOF机制避免了当前命令的写入日志时的阻塞,但这可能会带来潜在的阻塞风险。这是因为AOF日志写入也是在Redis的主线程中进行的。如果在将日志写入磁盘时,磁盘写入压力很大,这将导致写入操作非常缓慢,从而影响后续操作的执行。

经过仔细分析,你会发现这两种风险都与AOF写回磁盘的时机有关。这也就表明,如果我们能够精确控制命令执行后AOF日志写回磁盘的时机,那么这两种风险就能够得到有效地解决。

三种写回策略

关于AOF机制的问题,有三种不同的策略,对应于AOF配置项appendfsync的三个可选值。

然而,针对避免主线程阻塞和减少数据丢失问题,这三种写回策略都无法做到完美的平衡。以下是对它们的分析:

我把这三种策略的写回时机,以及优缺点汇总在了一张表格里,以方便你随时查看。

在这个阶段,我们可以根据系统对高性能和高可靠性的需求来选择适合的写回策略。总结来说:

然而,仅仅根据系统性能需求选择写回策略并不能完全保障系统的顺利运行。这是因为AOF以文件形式记录接收到的所有写命令。随着写命令的不断增加,AOF文件会变得越来越大。这会引发性能问题,主要体现在以下三个方面:

因此,我们必须采取控制措施来解决AOF文件过大的问题,而AOF重写机制就是其中一种解决方案。

日志文件太大了怎么办?

AOF重写机制的核心原理很简单,它的任务是根据数据库的当前状态,创建一个全新的AOF文件。这意味着它需要读取数据库中的所有键值对,然后为每个键值对生成一条相应的写入命令。例如,当它读取键值对"testkey": "testvalue"时,重写机制会记录一条"set testkey testvalue"的命令。这样,当需要进行故障恢复时,可以重新执行这些命令,以还原"testkey": "testvalue"的写入操作。

那么,AOF重写机制如何帮助减小日志文件的大小呢?实际上,它具有“多对一”的功能。这意味着,旧日志文件中的多个命令在重写后的新日志中变成了一条命令。

我们知道,AOF文件以追加的方式记录接收到的写命令。当一个键值对经历多次修改时,AOF文件会记录多条相应的写命令。然而,在重写过程中,根据键值对的当前状态,只生成一条对应的写入命令。这意味着,一个键值对在重写后的日志中只需要一条命令,而在日志恢复时,只需执行这一条命令,即可完全还原该键值对的写入操作。这种方式显著减小了AOF文件的体积,提高了性能。

下面这张图就是一个例子:

AOF重写减少日志大小

当我们对一个列表先后做了 6 次修改操作后,列表的最后状态是[“D”, “C”, “N”],此时,只用 LPUSH u:list “N”, “C”, "D"这一条命令就能实现该数据的恢复,这就节省了五条命令的空间。对于被修改过成百上千次的键值对来说,重写能节省的空间当然就更大了。

不过,虽然 AOF 重写后,日志文件会缩小,但是,要把整个数据库的最新数据的操作日志都写回磁盘,仍然是一个非常耗时的过程。这时,我们就要继续关注另一个问题了:重写会不会阻塞主线程?

AOF 重写会阻塞吗?

和 AOF 日志由主线程写回不同,重写过程是由后台线程 bgrewriteaof 来完成的,这也是为了避免阻塞主线程,导致数据库性能下降。

我把重写的过程总结为“一个拷贝,两处日志”。

“一个拷贝”就是指,每次执行重写时,主线程 fork 出后台的 bgrewriteaof 子进程。此时,fork 会把主线程的内存拷贝一份给 bgrewriteaof 子进程,这里面就包含了数据库的最新数据。然后,bgrewriteaof 子进程就可以在不影响主线程的情况下,逐一把拷贝的数据写成操作,记入重写日志。

“两处日志”又是什么呢?

因为主线程未阻塞,仍然可以处理新来的操作。此时,如果有写操作,第一处日志就是指正在使用的 AOF 日志,Redis 会把这个操作写到它的缓冲区。这样一来,即使宕机了,这个 AOF 日志的操作仍然是齐全的,可以用于恢复。

而第二处日志,就是指新的 AOF 重写日志。这个操作也会被写到重写日志的缓冲区。这样,重写日志也不会丢失最新的操作。等到拷贝数据的所有操作记录重写完成后,重写日志记录的这些最新操作也会写入新的 AOF 文件,以保证数据库最新状态的记录。此时,我们就可以用新的 AOF 文件替代旧文件了。

AOF非阻塞的重写过程

总结来说,每次 AOF 重写时,Redis 会先执行一个内存拷贝,用于重写;然后,使用两个日志保证在重写过程中,新写入的数据不会丢失。而且,因为 Redis 采用额外的线程进行数据重写,所以,这个过程并不会阻塞主线程。

小结

这篇文章详细介绍了Redis中用于防止数据丢失的AOF(Append-Only File)方法。这种方法通过逐一记录执行操作命令的方式,以确保在需要数据恢复时能够逐一执行这些命令,从而保证了数据的可靠性。

虽然这一方法看似相对简单,但它充分考虑了对Redis性能的潜在影响。总结来看,AOF日志提供了三种不同的写回策略,分别为Always、Everysec和No。这三种策略在可靠性方面从高到低排序,但在性能方面则正好相反,从低到高。

此外,为了避免AOF日志文件变得过大,Redis还引入了AOF重写机制。该机制通过后台线程根据数据库内数据的最新状态生成相应的插入命令,作为新的AOF日志。这个过程的设计避免了对主线程的阻塞,从而提高了系统的整体性能。

这三种写回策略突显了系统设计中的重要原则,即权衡。这意味着需要在性能和可靠性之间找到平衡。我相信这一原则对于系统设计和开发来说至关重要,希望你能深刻理解它,并在实际开发中应用得当。

然而,需要注意的是,数据持久化和AOF重写机制主要在"记录日志"过程中发挥作用。例如,选择合适的数据持久化时机可以避免在记录日志时阻塞主线程,而AOF重写机制则可以防止AOF日志文件无限增长。但在"使用日志"的过程中,即使用AOF进行故障恢复时,所有操作记录仍然需要逐一执行。考虑到Redis的单线程设计,这个"重放"过程可能会比较慢。

然而,是否有一种方法既能确保数据不丢失,又能更快地进行数据恢复呢?当然,这就是RDB快照的用武之地。在下一篇文章中,我们将深入研究RDB快照的工作原理和应用。

来源:码农本农内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯