代码编织梦想

在设计高并发、高性能的系统架构时,缓存是绕不开的一个话题,之所以用缓存,是因为不同的存储介质的访问速度存在巨大差异,例如SSD(固态硬盘)每秒钟可以读写几千次,而内存的随机读写速度是SSD的10万倍。使用内存作为缓存来加速应用程序的访问速度,是几乎所有高性能系统都会采用的方法。

缓存的思想很简单:把低速存储的数据,复制一份放到高速存储中,用来加速数据访问。

缓存的分类

缓存主要分为两大类:

  • 读写缓存
  • 只读缓存

这两类缓存的区别在于更新数据的时候是否经过缓存。

读写缓存

Kafka使用的PageCache就是典型的读写缓存。操作系统会利用系统空闲的物理内存来给文件读写做缓存,应用程序在写文件的时候,操作系统会先把数据写入到PageCache中,数据在成功写到PageCache之后,对于用户代码来说,写入就结束嘞。操作系统再通过异步的方式将数据更新到磁盘的文件中。应用程序在读文件的时候,操作系统也是先尝试从PageCache中寻找数据,如果找到就直接返回数据,找不到就会触发一个缺页中断,然后操作系统把数据从文件读取到PageCache中,再返回给应用程序。

我么可以看到写数据时,并不是同时将数据写到PageCache和磁盘上,这中间会有一个延迟。操作系统可以保证,即使是应用程序意外退出了,操作系统也会把这部分数据同步到磁盘上,但是如果服务器突然掉电了,这部分数据就会丢失。

读写缓存这种设计,天然就不是可靠的,这是一种牺牲数据一致性换取性能的设计。

写缓存的实现是非常复杂的,应用恒旭不停地更新PageCache中的数据,操作系统需要记录哪些数据有变化,同时还要在另外一个线程中,把缓存中变化的数据更新到磁盘中。在提供并发读写的同时来异步更新数据,这个过程中要保证数据的一致性,并且有非常好的性能,很不容易。

Kafka为什么可以使用PageCache提升性能?

Kafka可以使用PageCache并取得性能提升,有三个原因:

  1. 消息队列中数据的读写比例基本是1:1,我们用消息队列发送的大部分数据都是一收一发的。
  2. Kafka不是靠磁盘来保证数据的可靠性,它更依赖于不同节点上的多副本来解决数据可靠性问题。
  3. PageCache的读写缓存是操作系统实现的,Kafka只需要按照正确的方法来使用就可以了,不会涉及到实现复杂度的问题。

对于不同的使用场景,我们选择缓存的方式也有区别,如果读次数是写次数的几倍到几十倍,那么可以选择只读缓存,如果数据的读写次数基本一致,那么可以选择读写缓存。

只读缓存

对于只读缓存来说,我们需要考虑一个问题:缓存的数据来源于磁盘,那么应该怎么更新缓存中的数据呢?

我们可以有三种方法来更新只读缓存的数据:

  1. 数据更新时,同时更新磁盘和缓存,这种方法可能会带来数据不一致的问题,例如我们是选择同步还是异步来更新缓存?如果同步更新,磁盘更新成功了,缓存更新失败嘞,需要反复重试来保证更新成功吗?如果多次重试都失败,那么这次更新算成功还是失败呢?如果是异步更新缓存,怎么保证更新的时序?
  2. 定时将磁盘上的数据同步到缓存中,同步时可以采用全量更新,也可以选择增量更新。这种方法的缺点是缓存更新不会很及时,优点是实现起来非常简单。
  3. 我们不去更新缓存中的数据,而是给缓存中的每条数据设置一个比较短的过期时间,数据过期以后即使它还在缓存中,我们也会认为它不再有效,需要从磁盘中再次加载,这样就实现了数据更新。

缓存置换策略

当应用程序要访问某些数据时,如果这些数据在缓存中,那么直接访问缓存中的数据就可以了,这种情况我们称为一次缓存命中;如果数据不在缓存中,那只能去磁盘访问数据,我们称为缓存穿透

一般来说我们都会在数据首次被访问时,把这条数据放到缓存中,随着访问的数据越来越多,缓存空间会被占完,这时就需要把缓存中的一些数据删掉,以便存放新的数据,这个过程称为缓存置换

我们有两种缓存置换思路:

  1. 根据业务逻辑,定制化缓存置换策略。例如,当我们知道某些数据已经被删了,永远不会再访问到,那么优先置换这些数据是没有问题的。
  2. 使用通用的置换算法,例如LRU算法, 也称为最近最少使用算法,它的思想是最近刚刚被访问到的数据,它在将来被访问的可能性也很大,而很久都没有被访问过的数据,未来再被访问的几率也不大。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_54184443/article/details/129610419

聊聊前端缓存_光就一个字的博客-爱代码爱编程

基本的网络请求分为3个步骤:请求、处理、响应。 后端缓存主要集中在“处理”步骤,通过保持数据库链接,存储处理结果等方式缩短处理时间,尽快进入“响应”步骤。 前端缓存则可在剩下的两步:“请求”和“响应”中进行。在“请求”

聊聊计算机缓存-爱代码爱编程

文章目录 缓存概述缓存不命中缓存不命中的几种情况: 缓存通用组织结构cpu -> 从主存读取地址A->将A发送到高速缓存->那么如何在高速缓存中知道它包含地址A的数据的副

mysql缓存淘汰机制_聊聊缓存淘汰算法-LRU 实现原理-爱代码爱编程

前言 我们常用缓存提升数据查询速度,由于缓存容量有限,当缓存容量到达上限,就需要删除部分数据挪出空间,这样新数据才可以添加进来。缓存数据不能随机删除,一般情况下我们需要根据某种算法删除缓存数据。常用淘汰算法有 LRU,LFU,FIFO,这篇文章我们聊聊 LRU 算法。 LRU 简介 LRU 是 Least Recently Used 的缩写,这种

聊聊MyBatis缓存机制-爱代码爱编程

聊聊MyBatis缓存机制 文章链接 18778字 38分钟阅读 前言 MyBatis是常见的Java数据库访问层框架。在日常工作中,开发人员多数情况下是使用MyBatis的默认缓存配置,但是MyBatis缓存机制有一些不足之处,在使用中容易引起脏数据,形成一些潜

聊聊强缓存与协商缓存-爱代码爱编程

聊聊强缓存与协商缓存 前言一、强缓存二、协商缓存三、如何设置强缓存和协商缓存 前言 在学习强缓存与协商缓存之前,我们先聊聊什么是缓存? 缓存是指浏览器(客户端)在本地磁盘中对访问过的资源保存过的副本文件。 那么浏览器缓存有什么优点呢? 减少重复请求数据,避免通过网络再次加载资源,节省流量。降低服务器的压力,提升网站性能。加快客

聊聊Java中的缓存-爱代码爱编程

本文,我们主要聊一下Java中缓存的使用,几个点 Java对缓存的抽象——JSR107Spring对缓存的抽象——Spring CacheRedis如何集成到Spring中——作为Spring Cache的实现、直接使用RedisCache、使用RedisTemplate 先说点啥 缓存嘛,都知道是咋回事。常见的缓存如Memcached、Re

测试同学问我为什么每次让我清缓存(聊聊浏览器的缓存)-爱代码爱编程

前言 最近一个好奇的测试同学问我,你们前端开发完成后,每次都让我们清缓存或者Ctrl+f5强制刷新,我能不能每次不用强制刷新,就能看到你们更新的内容呢。我说是可以做到的,我来跟你讲讲浏览器的缓存策略。我相信应该有不少的同学在工作中都会遇到这种情况,让你的测试同学清缓存等。 缓存 浏览器缓存是为了节约网络的资源加速浏览,浏览器在用户磁盘上对最近请求过的

聊一聊缓存-爱代码爱编程

一、缓存存在的意义 在我看来缓存存在的意义只有一个,对于电商等服务化网站来说是 提升用户体验,对于单纯的系统来说是 提升系统运行效率。使用缓存解决的根本问题就是 防止高并发下系统宕机。 再细致一点可以往下分为: 减少磁盘IO、缓解DB压力加速DB中对强一致性不高的热点数据访问提高相应速度减少网络访问· 二、缓存常见问题及解决方案 1. 缓存穿透

聊聊缓存相关知识-爱代码爱编程

文章目录 缓存原理缓存穿透缓存击穿缓存雪崩穿透、击穿、雪崩对比缓存预热缓存更新缓存降级 缓存原理 缓存穿透 缓存穿透:指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库再查询一遍,然后返回空(相当于进行了两次无用的查询)。这样请求就绕过缓存直接查数据库,这也是经常提的缓存命中率

聊一聊浏览器缓存控制-爱代码爱编程

缓存是计算机领域一个很重要的概念,今天我们主要聊一聊浏览器中缓存的策略 首先聊一下需要缓存的时候的过程是什么样子: 客户端发起HTTP请求,服务器响应👇 响应内容包含所需数据和缓存规则(标示)并且浏览器会将数据和缓存规则存入浏览器缓存中👇 客户端再次发起上一请求,会带着缓存规则先向浏览器缓存询问,缓存是否过期👇 没有过期则直接返回缓存内

事务机制:redis能实现acid属性吗?-爱代码爱编程

ACID特性无需多言。我们知道关系数据库比如mysql可以实现事务的ACID特性,begin,commit,回滚实现。 那么redis可以实现ACID吗,结论是不能完全保证。 首先要知道redis通过MULTI关键字开启事

复杂链表,顺序表与链表的区别与缓存利用率问题的解释-爱代码爱编程

tips 之前讲的有关于删除,其实有两种不同的类型吧,Erase就是就是给我一个节点的地址,然后我把这个节点给他释放掉(删掉);还有一种就是remove,这个相当于就是说给我一个数值,然后我在链表当中把那个书给他删掉,那这个不就是find+Erase嘛,因此严格以上我们就没有必要提供remove了。 像之前的那个Erase函数,万一有人用pos传过

一文教你彻底打败redis bigkey和hotkey问题-爱代码爱编程

前言 bigkey和hotkey是Redis生产中两个比较常见的问题,本文从它们的概念、危害、发现、解决的角度,来分析一下这两个问题。 bigkey 概念 通俗易懂的讲,Big Key就是某个key对应的value很

图解 | 聊聊 mybatis 缓存_mybatis自定义缓存-爱代码爱编程

文章目录 一、MyBatis 缓存中的常用概念二、MyBatis 一级缓存2.1 一级缓存原理2.2 一级缓存配置2.3 一级缓存考题2.4 MyBatis 一级缓存失效的场景2.5 MyBatis 一级缓存总