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

news2024/9/23 13:25:25

今天是大年初一,祝大家新年快乐,新的一年技术增进,工资翻倍。

目前,Redis的持久化主要有两大机制,即AOF日志和RDB快照,在接下来的两节课里,我们就分别学习一下吧。

AOF日志是如何实现的?

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

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

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

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

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

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

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

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

首先,如果刚执行完一个命令,还没有来得及记日志就宕机了,那么这个命令和相应的数据就有丢失的风险。如果此时Redis是用作缓存,还可以从后端数据库重新读入数据进行恢复,但是,如果Redis是直接用作数据库的话,此时,因为命令没有记入日志,所以就无法用日志进行恢复了。

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

三种写回策略

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

  • Always,同步写回:每个写命令执行完,立马同步地将日志写回磁盘;
  • Everysec,每秒写回:每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区,每隔一秒把缓冲区中的内容写入磁盘;
  • No,操作系统控制的写回:每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘。

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

  • “同步写回”可以做到基本不丢数据,但是它在每一个写命令后都由一个慢速的落盘操作,不可避免地影响主线程性能;
  • 虽然“操作系统控制的写回”在写完缓冲区后,就可以继续执行后续的命令,但是落盘的时机已经不在Redis手中了,只要AOF记录没有写回磁盘,一旦宕机对应的数据就丢失了;
  • “每秒写回”采用一秒写回一次的频率,避免了“同步写回”的性能开销,虽然减少了对系统性能的影响,但是如果发生宕机,上一秒内未落盘的命令操作仍然会丢失。所以,这只能算是,在避免主线程性能和避免数据丢失两者取了个折中。

日志文件太大了怎么办?

简单来说,AOF重写机制就是在重写时,Redis根据数据库的现状创建一个新的AOF文件,也就说,读取数据库中的所有键值对,然后对每一个键值对用一条命令记录它的写入。比如说,当读取了键值对“testkey”:“testvalue”之后,重写机制会记录set testkey testvalue这条命令。这样,当需要恢复时,可以重新执行该命令,实现“testkey”:“testvalue”的写入。

为什么重写机制可以把日志文件变小呢?实际上,重写机制具有“多变一”功能。所谓的“多变一”,也就是说,旧日志文件中的多条命令,在重写后的新日志中变成了一条命令。

我们知道,AOF文件是以追加的方式,逐一记录接收到的写命令。当一共键值对被多条写命令修改时,AOF文件会记录相应的多条命令。但是,在重写的时候,是根据这个键值对当前的最新状态,为它生成对应的写入命令,这样一来,一共键值对在重写日志中只用一条命令就行了,而且,在日志恢复时,只用执行这条命令,就可以直接完成这个键值对的写入了。

学习来源:极客时间 《Redis核心技术与实战》学习笔记 Day07

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

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

相关文章

结构型模式-装饰器模式

1.概述 快餐店有炒面、炒饭这些快餐,可以额外附加鸡蛋、火腿、培根这些配菜,当然加配菜需要额外加钱,每个配菜的价钱通常不太一样,那么计算总价就会显得比较麻烦。 使用继承的方式存在的问题: 扩展性不好 如果要再加…

Alibaba微服务组件Sentinel学习笔记

1 .Sentinel 是什么 随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式服务架构的流量控制组件,主要以 流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的…

一篇读懂图神经网络

来源:投稿 作者:张宇 编辑:学姐 近年来,作为一项新兴的图数据学习技术,图神经网络(GNN)受到了非常广泛的关注,在各大顶级学术会议上,图神经网络相关的论文也占了相当可观…

https://app.diagrams.net/在线画图的一些技巧

最近工作需要,实践了在线画图的case, 下面就把使用心得记录一下: 关于diagrams 的一些小技巧: 登入的网页是:Flowchart Maker & Online Diagram Software 1: 利用group 的选项,这个可以整体移动,不用担心会漏掉一个: 就是选中一个图标,然后,看右边arrange 下面…

20230123使AIO-3568J开发板在Android12下永不休眠

20230123使AIO-3568J开发板在Android12下永不休眠 2023/1/23 13:59 1、 Z:\android12-rk3568-new\device\rockchip\common\device.mk # Bluetooth HAL PRODUCT_PACKAGES \ libbt-vendor \ android.hardware.bluetooth1.0-impl \ android.hardware.bluetooth1.0-se…

Hadoop基础之《(1)—大数据基本概念》

一、Hadoop 1、Hadoop大数据框架,处理分布式环境下数据存储和计算 2、Hadoop的HDFS处理存储 3、Hadoop的MapReduce处理计算 map让任务数据拆分到每一台去执行 reduce处理后的任务合并 4、Hive作用是在Hadoop上能够让用户来写SQL处理数据 Hive的执行引擎,…

深度学习TensorFlow—GPU2.4.0版环境配置,一文简单易懂详细大全,CUDA11.0、cuDNN8.0

深度学习TensorFlow—GPU2.4.0版环境配置,一文简单易懂详细大全,CUDA11.0、cuDNN8.0 前提:电脑拥有英伟达独立显卡!!!,并且安装了anaconda!!! 前提:电脑拥有英伟达独立显卡!!!&…

vue事件车之兄弟组件之间传值

目录前言一,全局事件总线介绍1.1 原理介绍1.2 x需要满足的条件二,知识点的复习2.1 vc是什么2.2 vm管理vc如何体现2.3 原型2.4 上述知识的串联三,实现需求3.1 x的编写及讲解3.2 使用x四,标准写法4.1 写法改动4.2 销毁五 关键代码后…

兔年首文迎新春-Cesium橘子洲烟花礼赞

兔年新春今天是兔年大年初二,神州大地,在经历了疫情的三年后迎来开放的一个春节。大家都沉浸在欢乐幸福的春节气氛中。玉兔迎新春,祝福齐送到:白兔祝你身体安康,黑兔祝你薪水高涨,灰兔送你梦想如意&#xf…

Maven高级

Maven高级 1,分模块开发 1.1 分模块开发设计 (1)按照功能拆分 我们现在的项目都是在一个模块中,比如前面的SSM整合开发。虽然这样做功能也都实现了,但是也存在了一些问题,我们拿银行的项目为例来聊聊这个事。 网络没有那么发…

Java多线程03——等待唤醒机制(and阻塞队列实现)

目录1.等待唤醒机制1.ThreadDemo2.Desk3.Cook4.Foodie2.等待唤醒机制(阻塞队列方式实现)1.ThreadDemo022.Cook023.Foodie023.线程的状态1.等待唤醒机制 生产者和消费者 桌子上有食物,消费者吃,桌子上没有食物,消费者等…

ElasticSearch 索引模板 组件模板 组合模板详细使用介绍

索引模板_template 文章目录索引模板_templateTemplate 介绍索引模板Index Template参数说明创建一个索引模板 Index Template测试不存在的索引直接添加数据创建索引总结组合索引模板 Index Template 7.8版本之后引入创建基于组件模板的索引模板 Index Template创建组件模板模拟…

LeetCode103_ 103. 二叉树的锯齿形层序遍历

LeetCode103_ 103. 二叉树的锯齿形层序遍历 一、描述 给你二叉树的根节点 root ,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。 示例 1&…

【头歌】顺序表的基本操作

第1关:顺序表的插入操作任务描述本关任务:编写顺序表的初始化、插入、遍历三个基本操作函数。相关知识顺序表的存储结构顺序表的存储结构可以借助于高级程序设计语言中的数组来表示,一维数组的下标与元素在线性表中的序号相对应。线性表的顺序…

YOLOv5/v7 引入 YOLOv8 的 C2f 模块

YOLOv8 项目地址:https://github.com/ultralytics/ultralytics YOLOv8 Ultralytics YOLOv8 是由 Ultralytics 开发的一个前沿的 SOTA 模型。它在以前成功的 YOLO 版本基础上,引入了新的功能和改进,进一步提升了其性能和灵活性。YOLOv8 基于快…

C 指针变量 取地址符的用法 *指针变量名的用法

文章目录IntroCode图示Intro C语言中有一类特殊的变量:指针变量(pointer variable),用于存储某个变量的内存地址的值。 要打印指针变量一般用%p格式符,会打印出该指针变量的值,即一个内存值。 Code // Created by wuyujin1997 …

【Linux】进程概念一

进程概念一 冯诺依曼体系结构 我们常见的计算机,如笔记本。我们不常见的计算机,如服务器,大部分都遵守冯诺依曼体系。 截止目前为止, 我们所认识的计算机,都是一个个的硬件组成 输入设备:包括键盘&#x…

如何使用JDBC操作数据库?JDBC API的使用详细解读

文章目录1. DriverManager1.1 注册驱动1.2 获取连接2. Connection2.1 获取执行sql的对象2.2 事务管理3. Statement4. ResultSet5. PreparedStatement5.1 sql注入问题5.2 preparedStatement 原理6. 总结Java编程基础教程系列1. DriverManager DriverManager ,驱动管…

C++模板不支持分离编译的问题

目录前言分离编译模式普通函数的分离编译(正常)模板函数的分离编译(出错)分析解决方式拓展--extern关键字extern"C"extern变量extern模板--控制实例化前言 分离编译模式 一个项目如果有多个源文件.c组成,每个源文件单独编译,形成目标文件。最…

Kubernetes:分享一个可以展示资源视图的 K8s开源 Web/桌面 客户端工具 Octant

写在前面 博文内容主要为 Octant 介绍以及 桌面/Web 端的安装教程涉及 Linux/Windows 的安装。理解不足小伙伴帮忙指正 其实当你什么都经历了,会发现,人生无论你怎么精心策划都抵不过一场命运的安排。 Octant 不是仪表板,Octant 是一个带有仪…