详解 Redis 中的 AOF 日志

news2024/10/6 20:35:07

AOF(Append Only File)追加写, AOF 日志它是写后日志,“写后”的意思是 Redis 是先执行命令,把数据写入内存,然后才记录日志,如下图所示:

后写日志有什么好处呢?

Redis 在写日志的时候并不会像 MySQL 那样有语法检查的,Redis 没有。所以先写日志在执行命令的话,日志中有可能记录了错误的命令,这样在故障恢复的时候可能恢复出不正确的数据。

而写后日志这样形式,让 Redis 先执行命令,如果命令不对客户端直接返回错误信息就 ok 了,正确的命令在执行完成之后在写入日志,那么 AOF 日志中的命令就都是正确的了。

AOF 后写还有一个好处就是不会阻塞当前正在执行的命令。

AOF 也有两个潜在的风险:

首先是如果刚执行完一个命令还没来得及写日志就宕机了,那么这条数据就无法恢复了。

其次,AOF 虽然避免了对当前命令的阻塞,但可能会给下一个操作带来阻塞风险。这是因为,AOF 日志也是在主线程中执行的,如果在把日志文件写入磁盘时,磁盘写压力大,就会导致写盘很慢,进而导致后续的操作也无法执行了。

这两个风险都是和写盘相关的,其实只要是我们掌握了写盘的时机,问题就迎刃而解了。

三种写回策略

对于这个问题,AOF 机制给我们提供了三个选择,也就是 AOF 配置项 appendfsync 的三个可选值。

  • Always:同步写回:每个写命令执行完,立马同步地将日志写回磁盘;

  • Everysec:每秒写回:每个写命令执行完,只是先把日志写到 AOF 文件的内存缓冲区,每隔一秒把缓冲区中的内容写入磁盘;

  • No:操作系统控制的写回:每个写命令执行完,只是先把日志写到 AOF 文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘。

针对避免主线程阻塞和减少数据丢失问题,这三种写回策略都无法做到两全其美。我们来分析下其中的原因。

  • Always 可以做到不丢失数据,但是次次都落盘,代价太高了。
  • Everysec 每秒写回,这个遇到特殊情况可能会丢失1s内的数据。
  • No 是将落盘的时机交给操作系统,至于特殊情况下宕机,丢的数据也就不知道是多少了,因为落盘是操作系统决定的了,外接无法干预。

总体上来说,Everysec 每秒写回这个是上述三种落盘方式中折中的一种了,既考虑了主线程的性能,又考虑了落盘的时间。

这三种策略的写回时机,以及优缺点汇总在了一张表格里

到这里,我们就可以根据系统对高性能和高可靠性的要求,来选择使用哪种写回策略了。总结一下就是:想要获得高性能,就选择 No 策略;如果想要得到高可靠性保证,就选择 Always 策略;如果允许数据有一点丢失,又希望性能别受太大影响的话,那么就选择 Everysec 策略。

每条命令执行完之后都写日志,那么日志文件太大了怎么办?

AOF 还有一个机制——重写机制,就是在重写时,Redis 根据数据库的现状创建一个新的 AOF 文件,也就是说,读取数据库中的所有键值对,然后对每一个键值对用一条命令记录它的写入。

**举个例子:**就是比如 key:value 这个键值对是经过了 k:va -> ke:valu -> key:value 这样的变化过程,那么在 AOF 日志文件中也有这三条命令所对应的日志。重写就是将多变一,将三条日志记录变为一条 key:value。

不过,虽然重写后文件确实是变小了,但是要把最新的日志写回磁盘,会不会阻塞主线程呢?

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

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

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

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/134209.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FPGA知识汇集-串行 RapidIO: 高性能嵌入式互连技术

本文摘自:德州仪器网站 串行RapidIO: 高性能嵌入式互连技术 | 德州仪器 (http://ti.com.cn) 串行RapidIO针对高性能嵌入式系统芯片间和板间互连而设计,它将是未来十几年中嵌入式系统互连的最佳选择。 本文比较RapidIO和传统互连技术的优点&#xff1b…

Windows内核--GUI显示原理(6.1)

传统的Windows图形处理 在Vista之前,图形子系统内核部分win32k.sys 通过DDI接口操作显示驱动, 显示驱动通过ENG接口调用win32k.sys. From: Windows 2000 显示体系结构 显示驱动程序的作用 不同显示驱动程序负责对于不同显示设备的优化。GDI仅负责标准位图…

使用python的parser.add_argument()在卷积神经网络中如何预定义参数?

在训练卷积神经网络时,需要预定义很多参数,例如batchsizebatch_sizebatchs​ize,backbone,dataset,datasetrootbackbone,dataset,dataset_rootbackbone,dataset,datasetr​oot等等,这些参数多而且特别零散,如果我们最初不把这些参…

我国制造行业 工业控制系统安全控制措施建设思考总结

声明 本文是学习GB-T 32919-2016 信息安全技术 工业控制系统安全控制应用指南. 下载地址 http://github5.com/view/585而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 工业控制系统安全控制概述 从概念上来说,工业控制系统的安全与其它领域…

【网络】网络发展,网络协议,网络传输流程,地址管理

目录 1.计算机网络背景 1.1网络发展 局域网和广域网 1.2 协议 2.网络协议初识 2.1协议分层 2.2OSI七层模型 2.3 TCP/IP 五层(或四层)模型 网络和操作系统之间的关系 2.4重谈协议 -- 计算机的视角,如何看待协议? 2.5 网…

python带你采集淘/苏/唯/考四大电商平台商品数据

前言 嗨喽,大家好呀~这里是爱看美女的茜茜呐 又到了学Python时刻~ 环境介绍: python 3.8 越稳定越好 pycharm 2021专业版 一、苏宁 模块使用: selenium >>> pip install selenium 3.141.0 Python当中的模块 操作 浏览器的驱动 Chrome浏览器 Chromedr…

2023北京国际残疾人用品展览会|福祉博览会

全 称:2023中国国际福祉博览会暨中国国际康复博览会 英 文:Care & Rehabilitation Expo China 2023 时 间:2023年5月21-23日 地 点:北京首钢会展中心(1-3号馆) 主 办:中国残疾人联合会 承 办…

visdrone数据集转化为MOT数据集(用作MOTR模型训练)

文章目录visdrone数据集转化为MOT数据集MOT17 数据集格式traindet.txtgt.txtseqinfo.initestdet.txtvisdrone——Task 4_ Multi-Object Tracking配置seqinfo.ini文件代码如下Linuxvisdrone数据集转化为MOT数据集 MOT17 数据集格式 ├── MOT17 │ ├── images │ ├─…

YOLO学习记录之模型修改

我们在做实验时,不免需要对模型结构进行修改来检测自己的改进性能,对于一般模型而言,我们只需要简单的在代码中添加网络层即可,但对于一些预训练好的模型,我们则需要进行较为复杂的修改。以我们的YOLOV7模型为例&#…

[Linux]----守护进程

文章目录前言一、什么是守护进程?二、会话和进程组会话进程组三、守护进程的编程流程总结前言 这节课我来给大家讲解在Linux下如何让进程守护化,运行在后台,处理我们的任务. 正文开始! 一、什么是守护进程? 守护进程也称为精灵进程(Daemon),是运行在后台的一种特殊进程.它…

Mybatis-Plus快速使用相关知识点1

Mybatis-Plus的mapper、service 基本CURD BaseMapper BaseMapper是MyBatis-Plus提供的模板mapper,其中包含了基本的CRUD方法,泛型为操作的实体类型,Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能…

JavaScript刷LeetCode拿offer-链表篇

一、链表 链表(Linked List)是一种常见的基础数据结构,也是线性表的一种。 一个线性表是 n 个具有相同特性的数据元素的有限序列,线性表的存储结构分为两类:顺序表(数组)和链表。 链表相比较顺…

站得高,望得远

1、站得高,望的远 计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决。 这句话几乎概括了计算机系统软件体系结构的设计要点 ,整个体系结构从上到下都是按照严格的层次结构设计的。不仅是计算机系统软件整个体系是这样的,体系里…

884. 两句话中的不常见单词 map与stringstream

目录 力扣884. 两句话中的不常见单词 【解法一】:最后写出了一坨屎,虽然它是一坨屎,但是它能动,虽然它是一坨屎,但起码这是我自己拉的 【大佬解法】 stringstream的使用 以及 map的使用 884. 两句话中的不常见单词 句…

python实现bib文件中参考文献的题目每个单词首字母大写

文章目录前言实现思路前言 由于毕业论文格式要求英文参考文献的题目的每个单词(除了介词)的首字母都要大写,如果一条条地自己修改费时费力,这里就想着简单地用python操作字符串的方式实现。 实现思路 观察bib参考文献格式&#x…

20230102单独编译Toybrick的TB-RK3588X开发板的Android12的内核

20230102单独编译Toybrick的TB-RK3588X开发板的Android12的内核 2023/1/2 17:40 《RK3588_Android12_SDK_Developer_Guide_CN.pdf》 原厂的开发板rk3588-evb1-lp4-v10单独编译内核的方式: cd kernel-5.10 export PATH../prebuilts/clang/host/linux-x86/clang-r4161…

【数据结构】C语言实现链表(单链表部分)

目录 前言 链表 链表的分类 1.单向或者双向 2.带头或者不带头 3.循环或者非循环 单链表实现 定义节点 接口函数实现 创建节点 打印链表 尾插节点 尾删节点 头插节点 头删节点 单链表查找 删除指定位置后的节点 指定位置后插入节点 删除指定位置 指定位置插入节点…

Linux-7 文本编辑vivim

Linux-7 文本编辑vi/vim vim介绍 什么是vim? vi和vim是Linux下的一个文本编辑工具。(可以李姐为Windows的记事本或word文档) 为什么要使用vim? 因为Linux系统一切皆为文件,而我们工作最多的就是修改某个服务的配置&a…

一名七年老安卓的 2022 总结

大家好,我是 shixin。一转眼到了 2022 的最后一天,今年发生了很多事,这篇文章来总结一下。长短期目标达成情况和去年一样,我的长期目标是成为具备创业能力的人,包括商业思维和全栈技术能力。总的来说,今年是…

STM32MP157驱动开发——USB设备驱动

STM32MP157驱动开发——USB设备驱动一、简介1.电气属性2.USB OTG3.STM32MP1 USB 接口简介4.Type-C 电气属性二、USB HOST 驱动开发1.USB HOST 驱动编写2.配置 PHY 控制器3.配置usbh_ehci三、USB HOST 测试1.鼠标键盘驱动使能2.U盘驱动四、USB OTG驱动开发1.USB OTG 控制器节点信…