操作系统缓存与缓冲

缓存与缓冲

缓冲区是一块临时存储数据的区域,这些数据后面会被传输到其他设备上。缓冲区更像消息队列,用以弥补高速设备和低速设备通信时的速度差,平衡读写速度。例如:IO中内核缓冲区Ring Buffer。

缓存:存在于速度相差较大的两种硬件之间,提高低速设备的访问速度,或者减少复杂耗时的计算带来的性能问题。缓存不一定在内存中,硬盘也可以!!比如从磁盘随机读取数据慢,从数据库查询数据慢。

缓存分类

常见的缓存主要就是静态缓存、分布式缓存和热点本地缓存这三种。

  • 静态缓存:对静态数据做缓存。

  • 分布式缓存:何针对动态请求做缓存,例如Redis。

  • 热点本地缓存主要部署在应用服务器的代码中,用于阻挡热点查询对于分布式缓存节点或者数据库的压力。

缓存的读写/更新策略?

Cache Aside(旁路缓存)策略

在这里插入图片描述

读策略的步骤是:

  • 从缓存中读取数据;
  • 如果缓存命中,则直接返回数据;
  • 如果缓存不命中,则从数据库中查询数据;
  • 查询到数据后,将数据写入到缓存中,并且返回给用户。

写策略的步骤是:

  • 更新数据库中的记录;
  • 删除缓存记录。

采取删除缓存的策略,不采用更新缓存的策略;以及先删除缓存再更新数据库都会产生数据不一致的问题。

Cache Aside 存在的最大的问题是当写入比较频繁时,缓存中的数据会被频繁地清理,这样会对缓存的命中率有一些影响。如果你的业务对缓存命中率有严格的要求,那么可以考虑两种解决方案:

  • 一种做法是在更新数据时也更新缓存,只是在更新缓存前先加一个分布式锁,因为这样在同一时间只允许一个线程更新缓存,就不会产生并发问题了。当然这么做对于写入的性能会有一些影响;

  • 另一种做法同样也是在更新数据时更新缓存,只是给缓存加一个较短的过期时间,这样即使出现缓存不一致的情况,缓存的数据也会很快地过期,对业务的影响也是可以接受。

应用:

如果我们的业务对缓存命中率有很高的要求,可以采用「更新数据库 + 更新缓存」的方案,因为更新缓存并不会出现缓存未命中的情况

但是在两个更新请求并发执行的时候,会出现数据不一致的问题。

解决办法:

  • 在更新缓存前先加个分布式锁,保证同一时间只运行一个请求更新缓存,就会不会产生并发问题了,当然引入了锁后,对于写入的性能就会带来影响。
  • 在更新完缓存时,给缓存加上较短的过期时间,这样即时出现缓存不一致的情况,缓存的数据也会很快过期,对业务还是能接受的。
redis延迟双删是什么?

针对「先删除缓存,再更新数据库」方案在「读 + 写」并发请求而造成缓存不一致的解决办法是「延迟双删」。

#删除缓存
redis.delKey(X)
#更新数据库
db.update(X)
#睡眠
Thread.sleep(N)
#再删除缓存
redis.delKey(X)

怎么保证「先更新数据库 ,再删除缓存」这两个操作能执行成功?

  • 重试机制。

    • 引入消息队列,将第二个操作(删除缓存)要操作的数据加入到消息队列,由消费者来操作数据。

      • 如果应用删除缓存失败,可以从消息队列中重新读取数据,然后再次删除缓存,这个就是重试机制。当然,如果重试超过的一定次数,还是没有成功,我们就需要向业务层发送报错信息了。

      • 如果删除缓存成功,就要把数据从消息队列中移除,避免重复操作,否则就继续重试。

        在这里插入图片描述

  • 订阅 MySQL binlog,再操作缓存。

    • 先更新数据库,再删缓存」的策略的第一步是更新数据库,那么更新数据库成功,就会产生一条变更日志,记录在 binlog 里。

    • 可以通过订阅 binlog 日志,拿到具体要操作的数据,然后再执行缓存删除,阿里巴巴开源的 Canal 中间件就是基于这个实现的。

      • Canal 模拟 MySQL 主从复制的交互协议,把自己伪装成一个 MySQL 的从节点,向 MySQL 主节点发送 dump 请求,MySQL 收到请求后,就会开始推送 Binlog 给 Canal,Canal 解析 Binlog 字节流之后,转换为便于读取的结构化数据,供下游程序订阅使用。
        在这里插入图片描述

Read/Write Through(读穿 / 写穿)策略

  • Write Through 的策略是这样的:先查询要写入的数据在缓存中是否已经存在,如果已经存在,则更新缓存中的数据,并且由缓存组件同步更新到数据库中,如果缓存中数据不存在,我们把这种情况叫做“Write Miss(写失效)”。不写入缓存中,而是直接更新到数据库中。

在这里插入图片描述

Write Back(写回)策略

写回的应用:操作系统层面的 Page Cache,Mysql日志的异步刷盘,亦或是消息队列中消息的异步写入磁盘,大多采用了这种策略。

缺点:因为缓存一般使用内存,而内存是非持久化的,所以一旦缓存机器掉电,就会造成原本缓存中的脏块儿数据丢失。所以你会发现系统在掉电之后,之前写入的文件会有部分丢失,就是因为 Page Cache 还没有来得及刷盘造成的。

主要区别:对于脏数据的落盘发生在命中或者挑选cache块。
在这里插入图片描述

应用
mysql中redo log binlog 的刷盘:凡是跟Page Cache打交道的操作
  • redo log的刷盘时机

    • MySQL 正常关闭时;
    • 当 redo log buffer 中记录的写入量大于 redo log buffer 内存空间的一半时,会触发落盘;
    • InnoDB 的后台线程每隔 1 秒,将 redo log buffer 持久化到磁盘。
    • 每次事务提交时都将缓存在 redo log buffer 里的 redo log 直接持久化到磁盘

    innodb_flush_log_at_trx_commit 参数:

    • 当设置该参数为 0 时,表示每次事务提交时 ,还是将 redo log 留在 redo log buffer 中 ,该模式下在事务提交时不会主动触发写入磁盘的操作。

      操作系统把缓存在 redo log buffer 中的 redo log ,通过调用 write() 写到操作系统的 Page Cache,然后调用 fsync() 持久化到磁盘。所以参数为 0 的策略,MySQL 进程的崩溃会导致上一秒钟所有事务数据的丢失;

    • 当设置该参数为 1 时,表示每次事务提交时,都将缓存在 redo log buffer 里的 redo log 直接持久化到磁盘,这样可以保证 MySQL 异常重启之后数据不会丢失。

    • 当设置该参数为 2 时,表示每次事务提交时,都只是缓存在 redo log buffer 里的 redo log 写到 redo log 文件,注意写入到「 redo log 文件」并不意味着写入到了磁盘,因为操作系统的文件系统中有个 Page Cache,Page Cache 是专门用来缓存文件数据的,所以写入「 redo log文件」意味着写入到了操作系统的文件缓存。

      调用 fsync,将缓存在操作系统中 Page Cache 里的 redo log 持久化到磁盘。所以参数为 2 的策略,较取值为 0 情况下更安全,因为 MySQL 进程的崩溃并不会丢失数据,只有在操作系统崩溃或者系统断电的情况下,上一秒钟所有事务数据才可能丢失
      在这里插入图片描述

  • binlog cache的刷盘时机?
    • sync_binlog = 0 的时候,表示每次提交事务都只 write,不 fsync,后续交由操作系统决定何时将数据持久化到磁盘;
    • sync_binlog = 1 的时候,表示每次提交事务都会 write,然后马上执行 fsync;
    • sync_binlog =N(N>1) 的时候,表示每次提交事务都 write,但累积 N 个事务后才 fsync。

在这里插入图片描述

redo log buffer 和 binlog cache都和page cache打交道,所以缓存都是写回策略。

redis 持久化刷盘

在这里插入图片描述

如果想要应用程序向文件写入数据后,能立马将数据同步到硬盘,就可以调用 fsync() 函数,这样内核就会将内核缓冲区的数据直接写入到硬盘,等到硬盘写操作完成后,该函数才会返回。

  • Always 策略就是每次写入 AOF 文件数据后,就执行 fsync() 函数;
  • Everysec 策略就会创建一个异步任务来执行 fsync() 函数;
  • No 策略就是永不执行 fsync() 函数

其实也是page cache。

kafka中数据持久化用到了page cache页缓存,同时实现了顺序读写

kafka持久化所用到的零拷贝+页缓存:

在这里插入图片描述

  • 零拷贝:Kafka的数据加工处理操作交由Kafka生产者和Kafka消费者处理。Kafka Broker应用层不关心存储的数据,所以就不用走应用层,传输效率高。
  • PageCache:Kafka重度依赖底层操作系统提供的PageCache功 能。当上层有写操作时,操作系统只是将数据写入PageCache。当读操作发生时,先从PageCache中查找,如果找不到,再去磁盘中读取。实际上PageCache是把尽可能多的空闲内存都当做了磁盘缓存来使用。

参考:
小林coding
极客时间操作系统40讲

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

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

相关文章

position: sticky; 网页吸顶效果,吸顶不遮盖容器滚动条

文章目录 一、效果二、创建容器三、监听滚动,切换 position四、引用 js 变量五、总结 一、效果 吸顶元素跟随页面向上滚动而滚动,达到一定高度后吸附在容器顶部;容器向下滚动到一定高度后,吸顶元素不再吸附,并跟随滚动…

如何选择适合自己的巴比达内网穿透方案

选择适合自己的巴比达内网穿透方案,需要考虑几个关键因素,包括您的具体需求、安全性要求、技术水平以及预算。以下是一些选择巴比达内网穿透方案的建议步骤: 1. 确定需求和用途 首先,需要明确您希望通过内网穿透实现的具体目标和…

CesiumJS【Basic】- #053 绘制渐变填充多边形(Entity方式)-使用canvas

文章目录 绘制渐变填充多边形(Entity方式)-使用canvas1 目标2 代码2.1 main.ts绘制渐变填充多边形(Entity方式)-使用canvas 1 目标 使用Entity方式绘制绘制渐变填充多边形 - 使用canvas 2 代码 2.1 main.ts import * as Cesium from cesium;const viewer = new Cesium…

量变引发质变,云微客AI矩阵系统以量取胜

我不允许还有老板在买大量的手机做矩阵,其实只需要一套云微客AI矩阵系统,就可以同时运营上百个矩阵账号。不需要买很多手机,也不用招很多运营人员来写文案、剪视频,AI矩阵系统自带智能创作、智能剪辑等功能,只需要上传…

java设计模式(五)建造者模式(Builder Pattern)

1、模式介绍: 建造者模式(Builder Pattern)是一种创建型设计模式,它允许你创建一个复杂对象的表示,同时隐藏了创建细节。该模式将对象的构建过程和表示分离,使得相同的构建过程可以创建不同的表示。 2、应…

零基础入门GIS开发,必看实用教程【附智慧校园实战笔记源码】

GIS开发也叫webgis,web就是指网页端,所以GIS开发大部分情况下是指网页端的地图可视化开发。 因此GIS开发需要学习前端开发HTML/CSS/JS,以及一些常见的前端框架,例如vue和react等(新中地教育通常是教vue,其…

ssm三农产品助推网站-计算机毕业设计源码91990

目录 摘要 1 绪论 1.1选题背景与意义 1.2国内外研究现状 1.3论文结构与章节安排 2网站分析 2.1 可行性分析 2.2 网站流程分析 2.2.1 数据流程 2.2.2 业务流程 2.3 网站功能分析 2.3.1 功能性分析 2.3.2 非功能性分析 2.4 网站用例分析 2.5本章小结 3 网站总体设…

这次发现的开源版本我愿意称之为最具学习价值的商城系统|商城源码点击进入

这是一款我发现的强大、灵活、易用的商城系统,成为我的的首选商城框架,让我的商城开发事半功倍!这款开源商城项目具有多元的商业模式满足了任何使用场景的需求。 有S2B2C供应链商城、B2B2C多商户商城、O2O外卖商城、B2C单商户商城、社区团购、…

Hive查询优化 - 面试工作不走弯路

引言:Hive作为一种基于Hadoop的数据仓库工具,广泛应用于大数据分析。然而,由于其依赖于MapReduce框架,查询的性能可能会受到影响。为了确保Hive查询能够高效运行,掌握查询优化技巧至关重要。在日常工作中,高…

Python入门 2024/7/3

目录 for循环的基础语法 遍历字符串 练习:数一数有几个a range语句 三个语法 语法1 语法2 语法3 练习:有几个偶数 变量作用域 for循环的嵌套使用 打印九九乘法表 发工资案例 continue和break语句 函数的基础定义语法 函数声明 函数调用 …

使用CiteSpace软件对知网文献进行关键词共现/聚类/突现分析

🤵‍♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞&#x1f4…

前端进阶全栈计划:Spring扫盲

Spring扫盲 spring 和 springboot的关系? 类比前端:vue.js和nuxt.js的关系 Spring Boot 是基于 Spring 框架的快速开发工具,简化了 Spring 应用的配置和部署。 spring核心特性 1. 依赖注入 依赖注入是Spring框架的核心功能之一。它允许你通过配置将对…

Windows系统安装MySQL8.0.38

MySQL 8.0 相对于 MySQL 5.7 来说有几个显著的区别和改进,以下是一些主要的区别: JSON 数据类型和函数改进: MySQL 8.0 引入了更多的 JSON 支持,包括 JSON 数据类型、JSON 函数和操作符。这使得存储和查询 JSON 数据更加方便和高效…

从头开始构建 RAG 的 LLM 代理:综合指南

GPT-3、GPT-4 等 LLM 及其开源版本经常难以检索最新信息,有时会产生幻觉或不正确的信息。 检索增强生成 (RAG)是一种将 LLM 的强大功能与外部知识检索相结合的技术。RAG 使我们能够将 LLM 响应建立在事实、最新的信息之上,从而显著提高 AI 生成内容的准…

还敢乱买智能猫砂盆?今天扒一扒糯雪、鸟语花香、CEWEY智能猫砂盆!

在这高科技迅速发展的时代,连猫咪用来拉屎的屎盆子也变成了全自动化,从普通的猫砂盆变成了智能猫砂盆,让铲屎官再也不用每天赶回家铲屎给猫整理烂摊子,实在是非常轻松。所以那个时候的我也果断扔掉了家里的猫砂盆,转而…

电子电路学习笔记(4)三极管

部分内容参考链接: 电子电路学习笔记(5)——三极管_三极管 箭头-CSDN博客 模拟电子技术基础笔记(4)——晶体三极管_集电结的单向导电性-CSDN博客 硬件基本功-36-三极管Ib电流如何控制Ic电流_哔哩哔哩_bilibili MOS…

使用DC/AC电源模块时需要注意的事项

BOSHIDA 使用DC/AC电源模块时需要注意的事项 1. 仔细阅读和理解产品说明书:在使用DC/AC电源模块之前,应该仔细阅读和理解产品说明书,了解其性能特点、技术要求和使用方法,以确保正确使用和避免潜在的安全风险。 2. 选择适当的电…

源代码编译安装LAMP

Apache简介 主要特点 开放源代码,跨平台应用 支持多种网页编程程序 模块化设计,运行稳定,良好得安全性 软件版本 1.X 目前最高版本是1.3,运行稳定 向下兼容性较好,但缺乏一些较新得功能 2.X 目前最高版本是2.4 …

PDF处理篇:如何调整 PDF 图像的大小

将视觉效果无缝集成到 PDF 中的能力使它们成为强大的通信工具。然而,笨拙的图像大小会迅速扰乱文档的流程,阻碍清晰度和专业性。幸运的是,GeekerPDF 和Adobe Acrobat等流行的应用程序提供了用户友好的解决方案来应对这一挑战。这个全面的指南…

Google 发布了最新的开源大模型 Gemma 2,本地快速部署和体验

Gemma 2 是 Google 最新发布的开源大语言模型。它有两种规模:90 亿(9B)参数和 270 亿(27B)参数,分别具有基础(预训练)和指令调优版本,拥有 8K Tokens 的上下文长度&#…