操作系统缓存与缓冲

缓存与缓冲

缓冲区是一块临时存储数据的区域,这些数据后面会被传输到其他设备上。缓冲区更像消息队列,用以弥补高速设备和低速设备通信时的速度差,平衡读写速度。例如: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讲

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

鸿蒙应用开发之Badge容器

在开发应用的时候,经常需要一些提示,特别当用户打开应用时,有一些事情需要提醒一下用户,但是不能自动打开这个窗口提示,这样会让用户比较烦。所以设计一些提示显示来告诉用户,这里有新东西了,赶紧来点击一下查看。 比如像下面例子显示的界面: 在这里显示红点的地方,就…

区块链加载解析方法

一.区块链加载解析 对于数据的下载主要包括三种方式: 1.实现比特币网络协议,通过该协议和其他比特币全节点建立联系,然后同步区块数据。 2.通过比特币节点提供的API服务下载区块链数据。 3.通过blickchain.com提供的rest服务下载区块数据…

Python可实现各种算法库之algorithms使用详解

概要 在软件开发和计算机科学领域,算法是解决问题的核心工具。Python 作为一种广泛使用的编程语言,提供了多种内置和第三方库来实现各种算法。algorithms 库是一个集合了多种常用算法和数据结构的 Python 库,旨在帮助开发者快速实现和应用这些算法。本文将详细介绍 algorit…

【 2024!深入了解 大语言模型(LLM)微调方法(总结)】

引言 众所周知,大语言模型(LLM)正在飞速发展,各行业都有了自己的大模型。其中,大模型微调技术在此过程中起到了非常关键的作用,它提升了模型的生成效率和适应性,使其能够在多样化的应用场景中发挥更大的价值。 那么&…

C++ Linux调试(无IDE)

跨平台IDE编译调试C很方便,如QTCreate 、VSCode、Eclipse等,但是如果只能使用Shell控制台呢,gdb调试的优势就很明显了,在没有IDE的情况下,这个方式最有效。因为上手不是很难,特此整理 参考链接 目录 1、G…

MAC下打印机启用用户代码(RICOH理光打印机)

之前一直用Windows操作公司打印机,最近研究了下用MAC(macos 13.6.7)也能成功打印。公司为了防止恶意打印,因此对打印机设置了用户代码,输入正确的用户代码才能打印,因此配置会复杂一些。 1.安装适配的打印机…

5分钟教你用AI把老照片动起来,别再去花49块9的冤枉钱了

文章目录 需要的工具 最近,AI视频在各大平台上,又火了。 只是火的形式,变成了将老照片动起来,打情感牌,或者做很多经典电视剧的再整活。 直接把可灵的生成时间,从以前的4分钟,生生的干成了20分钟…

【APK】Unity出android包,报错 Gradle build failed.See the Console for details

参考大佬的博客:报错:Gradle build failed.See the Console for details.(已解决)_starting a gradle daemon, 1 incompatible daemon co-CSDN博客 本地出Android包,Build失败 解决办法: 1.下载一个低版本…

如何在多个服务器上安装WordPress分布式部署

许多网络主机现在保证其服务的正常运行时间为 99.9%,但这仍然每年最多有 8.7 小时的停机时间。 许多公司不能够承担这种风险。例如。在超级碗比赛中失败的体育新闻网站可能会失去忠实的追随者。 我们通过设置维护高可用性 WordPress分布式部署配置来帮助 WordPres…

SF-HCI-SAP问题收集17:值映射布尔型EC数据

Complacency is the enemy of study 学习的敌人是自己的满足。 SAP SuccessFactors Employee Central 到 SAP ERP 的员工主数据复制 successfactor employee center主数据同步,一直以来排错比较难,难的地方是这个提示消息比较隐晦,而且同步的…

C#的多线程UI窗体控件显示方案 - 开源研究系列文章

上次编写了《LUAgent服务器端工具》这个应用,然后里面需要新启动一个线程去对文件进行上传到FTP服务器,但是新线程里无法对应用主线程UI的内容进行更改,所以就需要在线程里设置主UI线程里控件信息的方法,于是就有了此博文。此文记…

程序员学CFA——经济学(五)

经济学(五) 货币政策与财政政策基本术语货币政策货币货币的功能货币的定义货币的创造过程货币的供给和需求费雪效应 中央银行中央银行的职能中央银行的目标与通货膨胀的成本中央银行的有效性 货币政策工具货币传导机制货币政策的目标与形式货币政策的目标…

大象机器人开源协作机械臂机械臂接入GPT4o大模型!

本文已经或者同济子豪兄作者授权对文章进行编辑和转载 引言 随着人工智能和机器人技术的快速发展,机械臂在工业、医疗和服务业等领域的应用越来越广泛。通过结合大模型和多模态AI,机械臂能够实现更加复杂和智能化的任务,提升了人机协作的效率…

Linux 压测工具---ab

安装 yum -y install httpd-tools 本文用于压测k8s集群内pod,k8s集群master可直接测试pod ip 命令: ab -n 10000 -c 100 http://10.42.8.212/ 其中,-n表示请求数,-c表示并发数,ip必须有”/“,表示此目录…

k8s上部署单节点apache-lotdb

一、yaml文件 使用的nfs的动态存储类,需要提前搭建。 # cat iotdb_deployment.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata:name: logsnamespace: lotdb spec:storageClassName: "nfs-client"accessModes:- ReadWriteManyresources:req…

[图解]企业应用架构模式2024新译本讲解21-数据映射器3

1 00:00:00,040 --> 00:00:03,300 接下来,我们就来看一下代码的示例了 2 00:00:06,910 --> 00:00:09,180 我们同样一步一步来看一下 3 00:00:35,030 --> 00:00:36,950 首先初始化数据 4 00:00:37,870 --> 00:00:41,620 这个地方跟之前我们举的例子是…

2024年小米SU7维修手册和电路图线路图接线图资料更新

此次更新了2024年小米SU7维修手册和电路图资料,覆盖市面上99%车型,包括维修手册、电路图、新车特征、车身钣金维修数据、全车拆装、扭力、发动机大修、发动机正时、保养、电路图、针脚定义、模块传感器、保险丝盒图解对照表位置等等! 汽修帮…

ImportError cannot import name ‘uic‘ from ‘PyQt5‘

ImportError cannot import name ‘uic’ from ‘PyQt5’ 1、描述 使用nuitka把PyQt5打包exe文件时报错: ImportError cannot import name ‘uic’ from ‘PyQt5’ 2、原因 这个是由于无法找到uic的目录导致的,在PyQt5的目录下是有uic文件的。 3、解决方案 找到导入uic…

常见sql语句练习

Tips:之前查看网上的文章感觉太乱了,所以自己整理了一套sql语句来练习,主要也可以拿来应对面试,需要的可以自行下载练习 包含基本语句、聚合函数、模糊查询、范围查询、排序、聚合、分组、分页、子查询、索引和视图、左右连接、双…

电脑突然不能上网,然后网线是正确的,网络诊断提示说,显示远程计算机或设备将不接受连接

解决方法: WINR输入 cmd 点击确认,输入inetcpl.cpl,点击确定,弹出右边窗口。 电脑显示远程计算机或设备将不接受连接的解决办法,已解决