宕机了,Redis数据丢了怎么办?

  • 前言
  • 什么是AOF?
  • 三种写回策略
  • 日志文件太大怎么办?
  • AOF重写会阻塞主线程吗?
  • AOF的缺点
  • 总结
  • 什么是RDB?
  • 给哪些数据做快照?
  • 快照时能够修改数据吗?
  • 多久做一次快照?
  • 增量快照
  • AOF和RDB混合使用
  • 总结
  • 总结

Redis作为内存型的数据库,虽然很快,依然有着很大的隐患,一旦 「 服务器宕机」重启,内存中数据还会存在吗?

很容易想到的一个方案是从后台数据恢复这些数据,如果数据量很小,这倒是一个可行的方案。但是如果数据量过大,频繁的从后台数据库访问数据,压力很大;另外一方面恢复数据的时间极慢。

对于 Redis来说,实现数据的持久化和快速恢复是至关重要。

今天这篇文章就来介绍一下 Redis持久化的两种机制 AOF日志、 RDB快照。

什么是 AOF 日志?

AOF(Append Only File)日志称之为 「 写后日志」,即是命令先执行完成,把数据写入内存,然后才会记录日志。

AOF日志(文本形式)会将收到每一条的命令且执行成功的命令以一定的格式写入到文本中(追加的方式)。

「 写后日志有什么好处呢?」 如下:

但是 AOF日志也有 「 潜在的风险」,分析如下:

为了解决上面的风险, AOF日志提供了三种回写策略。

AOF机制提供了三种回写策略,这些都在 appendfsync配置,如下:

其实这三中写回策略都无法解决主线程的阻塞和数据丢失的问题,分析如下:

以上三种策略优缺点总结如下表:

随着数据量的增大,AOF日志文件难免会很大,这样将会导致写入和恢复数据都将变得非常慢。此时AOF提供了一种 「 重写机制」解决这一问题。

❝重写机制理解起来很简单,即是 Redis会创建一个新的 AOF日志文件,将每个键值对最终的值用一条命令写入日志文件中。

比如读取了键值对 key1:value1,重写机制会在新的AOF日志文件中记录如下一条命令:

set key1 value1

其实即是记录多次修改的最终的值记录在新的AOF日志文件中,这样当恢复数据时可直接执行该命令。

「 为什么重写机制能够缩小文件呢?」 当一个键值被多次修改后, AOF日志文件中将会记录多次修改键值的命令,重写机制是根据这个键值最新状态为它生成 「 写入」命令,这样旧文件中的 「 多条」命令在重写后的新日志中变成了 「 一条」命令。

作者画了一张重写流程图,仅供参考,如下:

AOF重写虽然能够缩减日志文件的大小,达到减少日志记录和数据恢复的时间,但是在数据量非常的大情况下把整个数据库重写后的日志写入磁盘是一个非常耗时的过程,难道不会阻塞主线程吗?

「 答案是:不会阻塞主线程」; 因为AOF重写过程是由后台子进程 bgrewriteaof来完成的,这也是为了避免阻塞主线程,导致数据库性能下降。

其实重写的过程分为两个阶段: 「 一个拷贝,两处日志」

「 一个拷贝」:指每次执行重写时,主线程都 fork一个子线程 bgrewriteaof,主线程会把内存数据拷贝一份到子线程,此时子线程中包含了数据库的最新数据。然后子线程就能在不影响主线程的情况下进行AOF重写了。

「 两处日志」是什么?如下:

虽说进行了日志重写后,AOF日志文件会缩减很多,但是在数据恢复过程中仍然是一条命令一条命令(由于单线程,只能顺序执行)的执行恢复数据,这个恢复的过程非常缓慢。

AOF这种通过逐一记录操作命令的日志方式,提供了三种写回策略保证数据的可靠性,分别是 AlwaysEverysecNo,这三种策略在可靠性上是从高到低,而在性能上则是从低到高。

为了避免日志文件过大,Redis提供了重写的机制,每次重写都fork一个子线程,拷贝内存数据进行重写,将多条命令缩减成一条生成键值对的命令,最终重写的日志作为新的日志。

什么是RDB?

RDB(Redis DataBase)是另外一种持久化方式:内存快照。

RDB记录的是 「 某一个时刻」的内存数据,并不是操作命令。

这种方式类似于拍照,只保留某一时刻的形象。内存快照是将某一时刻的状态以文件的形式写入磁盘。这样即使宕机了,数据也不会丢失,这个快照文件就称为 RDB文件。

❝由于记录的是某个时刻的内存数据,数据恢复非常快的,不需要像AOF日志逐一执行记录的命令。

为了保证数据的可靠性,Redis执行的 「 全量快照」,也就是把内存中的所有数据都写到磁盘中。

随着数据量的增大,一次性把全部数据都写到磁盘中势必会造成线程阻塞,这就关系到Redis的性能了。

针对线程阻塞的问题Redis提供了两个命令,如下:

这样就可以使用 bgsave命令执行全量快照,既可以保证数据的可靠性也避免了主线程的阻塞。

子线程执行全量快照的同时,主线程仍然在接受着请求,读数据肯定没有问题,但是如果个修改了数据,如何能够保证快照的完整性呢?

「 举个栗子」:我在 T时刻进行全量快照,假设数据量有 8G,写入磁盘的过程至少需要 20S,在这 20S的时间内,一旦内存中的数据发生了修改,则快照的完整性就破坏了。

但是如果在快照时不能修改数据,则对Redis的性能有巨大的影响,对于这个问题,Redis是如何解决的呢?

Redis借助操作系统提供的 写时复制技术(Copy-On-Write, COW),在执行快照的同时,正常处理写操作。

其实很简单, bgsave命令会 fork一个子线程,这个子线程共享所有内存的数据,子线程会读取主线程内存中的数据,将他们写入 RDB文件。

如上图,对于 键值对A的读取并不会影响子线程,但是如果主线程一旦修改内存中一块数据(例如 键值对D),这块数据将会被复制一个副本,然后 bgsave子线程会将其写入 RDB文件。

快照只是记录某一时刻的数据,一旦时间隔离很久,则服务器一旦宕机,则会丢失那段时间的数据。

比如在 T1时间做了一次快照,在 T1+t时又做了一次快照,如果在 t这个时间段内服务器突然宕机了,则快照中只保存了 T1时刻的快照,在 t时间段内的数据修改未被记录(丢失)。如下图:

从上图明显可以看出, RDB 并不是一个完美的日志记录方案」,只有让 t时间逐渐缩小,才能保证丢失的数据缩小。

「 那么问题来了,时间能够缩短 1秒 吗?」 即是每秒执行一次快照。

❝全量快照是记录某一个时刻的 「 全部」内存数据,每秒执行一次的对Redis性能影响巨大,于是 「 增量快照」就出来了。

「 增量快照是指做了一次全量快照之后,后续的快照只对修改的数据进行快照记录」,这样可以避免每次都全量快照的开销。

增量快照的前提是Redis能够记住修改的数据,这个功能其实开销也是巨大的,需要保存完整的键值对,这对内存的消耗是巨大的。

❝为了解决这个问题,Redis使用了 AOFRDB混合使用的方式。

这个概念是在 Redis4.0提出的,简单的说就是 「 内存快照以一定的频率执行,比如1小时一次,在两次快照之间,使用AOF日志记录这期间的所有命令操作。」

❝混合使用的方式使得内存快照不必频繁的执行,并且AOF记录的也不是全部的操作命令,而是两次快照之间的操作命令,不会出现AOF日志文件过大的情况了,避免了AOF重写的开销了。

这个方案既能够用到的RDB的快速恢复的好处,又能享受都只记录操作命令的简单优势,强烈建议使用。

RDB内存快照记录的是某一个时刻的内存数据,因此能够快速恢复; AOFRDB混合使用能够使得宕机后数据快速恢复,又能够避免 AOF日志文件过大。

本文介绍了两种数据恢复和持久化的方案,分别是 AOFRDB

AOF介绍了什么?如下:

RDB介绍了什么?如下:

Original: https://www.cnblogs.com/Chenjiabing/p/14029943.html
Author: 爱撒谎的男孩
Title: 宕机了,Redis数据丢了怎么办?

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/711445/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • C++ STL 常用容器概述

    前排提醒: 由于 Microsoft Docs 全是机翻。所以本文表格是我人脑补翻+审校。 如果有纰漏、模糊及时反馈。 了解每一种容器的特性、知道什么情况下用什么容器就可以。 序列…

    技术杂谈 2023年6月21日
    093
  • 挖矿病毒 qW3xT.2 最终解决方案

    转自:https://blog.csdn.net/hgx13467479678/article/details/82347473 1,cpu 100%, 用top 查看cpu100…

    技术杂谈 2023年6月1日
    084
  • LDD3源码分析之poll分析

    编译环境:Ubuntu 10.10 内核版本:2.6.32-38-generic-pae LDD3源码路径:examples/scull/pipe.c examples/scull…

    技术杂谈 2023年5月31日
    060
  • C# 坐标系

    一、概述 从数学角度讲,Point是一个二维矢量,包含两个公共整型属性,属性用大写X和Y(c#中公共属性一般约定以大写字母开头)。当坐标不是整数值是float时,用PointF代替…

    技术杂谈 2023年6月1日
    087
  • spring boot+log4j2快速使用(一)

    log4j是Apache的一个开源项目,log4j2和log4j是一个作者,只不过log4j2是重新架构的一款日志组件,他抛弃了之前log4j的不足,以及吸取了优秀的logback…

    技术杂谈 2023年7月11日
    0100
  • collection库更新1.4.0版本

    collection库一直在使用中,周末集合github上的反馈以及contributor的修改,更新了1.4.0版本。 这个版本做了几个事情: 增加了三种类型, uint, ui…

    技术杂谈 2023年6月1日
    0101
  • KMP算法学习记录

    Foreword: 初学KMP匹配算法,不得其门,总感觉自己想,想不出来,看书上文字解释晦涩难懂。不能准确的捕捉算法设计时候的灵光和思路 。于是自己试着完成了一遍,现将过程记录下来…

    技术杂谈 2023年6月21日
    086
  • 技术漫谈之——Jectpack Compose

    最近Jetpack Compose发布了Beta版本,抽时间了解了一下Compose带来的改变和其中的一些原理。本文不会讲解具体API,只是比较随意的分享自己的一些疑问以及在探寻答…

    技术杂谈 2023年7月11日
    062
  • ASP.NET CORE WEB项目介绍

    首先创建一个asp.net core web应用程序 第二步 目前官方预置了7种模板项目供我们选择。从中我们可以看出,既有我们熟悉的MVC、WebAPI,又新添加了Razor Pa…

    技术杂谈 2023年6月21日
    094
  • 记一次Linux server偶发CPU飙升问题的跟进与解决

    进入6月后,随着一个主要功能版本api的上线,服务端的QPS翻了一倍,平时服务器的CPU使用稳定在30%上下,高峰期则在60%上下,但是偶尔会有单台机器出现持续数分钟突然飙到90%…

    技术杂谈 2023年6月21日
    095
  • 【对话生成】常见对话生成数据集整理,含下载链接(更新至2022.06.04)

    本文主要整理对话生成领域相关的数据集,尤其是开放域对话生成。当前可以把开放域对话生成任务划分为:传统开放域对话生成、多模态对话生成、情感对话生成、个性化对话生成、策略控制对话生成等…

    技术杂谈 2023年7月24日
    077
  • 【HarmonyOS】【ARK UI】HarmonyOS ets语言怎么实现双击返回键退出

    ​ 参考资料 【Harmony OS】【ARK UI】Date 基本操作 自定义组件生命周期回调函数 弹窗 代码运行 思路: 定义一个全局变量,判断点击时间与上一次点击时间差,若大…

    技术杂谈 2023年5月31日
    090
  • Http和Https

    Http和Https 首先我们介绍一下http和https,http是超文本传输协议,无状态并且是明文传输。https是在http协议的基础上增加了SSL/TLS协议,设备之间的通…

    技术杂谈 2023年6月21日
    0102
  • HTTPS:让数据传输更安全

    浏览器安全主要划分为三大块内容:页面安全、系统安全和网络安全。前面我们用四篇文章介绍了页面安全和系统安全,也聊了浏览器和 Web 开发者是如何应对各种类型的攻击,本文是我们专栏的最…

    技术杂谈 2023年5月31日
    087
  • Codeforces Round #750 (Div. 2)

    Codeforces Round #750 (Div. 2) A. Luntik and Concerts 思路分析: 首先我们可以肯定的是a,b,c都大于等于1,所以我们先让它们…

    技术杂谈 2023年7月24日
    061
  • 关于高斯-博内-陈定理

    平面上任一三角形的三内角之和恒等于π,对于一般曲面上由三条测地线构成的三角形,其内角和等于π加上高斯曲率K在此三角形所围曲面上的积分. 1827年,高斯证明了这一定理. 1944年…

    技术杂谈 2023年5月31日
    075
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球