For investors
股价:
5.36 美元 %For investors
股价:
5.36 美元 %认真做教育 专心促就业
缓存在许多软件编程开发项目中是会经常用到的一个软件开发技术,而本文我们就通过案例分析来简单了解一下,缓存的作用与用法分享。
缓存优化性能的原理和索引一样,是拿额外的存储空间换取查询时间。缓存无处不在,设想一下我们在浏览器打开这篇文章,会有多少层缓存呢?
先解析DNS时,浏览器一层DNS缓存、操作系统一层DNS缓存、DNS服务器链上层层缓存;
发送一个GET请求这篇文章,服务端很可能早已将其缓存在KV存储组件中了;
即使没有击中缓存,数据库服务器内存中也缓存了近查询的数据;
即使没有击中数据库服务器的缓存,数据库从索引文件中读取,操作系统已经把热点文件的内容放置在PageCache中了;
即使没有击中操作系统的文件缓存,直接读取文件,大部分固态硬盘或者磁盘本身也自带缓存;
数据取到之后服务器用模板引擎渲染出HTML,模板引擎早已解析好缓存在服务端内存中了;
历经数十毫秒之后,终于服务器返回了一个渲染后的HTML,浏览器端解析DOM树,发送请求来加载静态资源;
需要加载的静态资源可能因Cache-Control在浏览器本地磁盘和内存中已经缓存了;
即使本地缓存到期,也可能因Etag没变服务器告诉浏览器304NotModified继续缓存;
即使Etag变了,静态资源服务器也因其他用户访问过早已将文件缓存在内存中了;
加载的JS文件会丢到JS引擎执行,其中可能涉及的种种缓存就不再展开了;
整个过程中链条上涉及的所有的计算机和网络设备,执行的热点代码和数据很可能会载入CPU的多级高速缓存。
这里列举的仅仅是一部分常见的缓存,就有多种多样的形式:从廉价的磁盘到昂贵的CPU高速缓存,终目的都是用来换取宝贵的时间。
多线程并发编程需要用各种手段(比如Java中的synchronizedvolatile)防止并发更新数据,一部分原因就是防止线程本地缓存的不一致;
缓存失效衍生的问题还有:缓存穿透、缓存击穿、缓存雪崩。解决用不存在的Key来穿透攻击,需要用空值缓存或布隆过滤器;解决单个缓存过期后,瞬间被大量恶意查询击穿的问题需要做查询互斥;解决某个时间点大量缓存同时过期的雪崩问题需要添加随机TTL;
热点数据如果是多级缓存,在发生修改时需要清除或修改各级缓存,这些操作往往不是原子操作,又会涉及各种不一致问题。
除了通常意义上的缓存外,对象重用的池化技术,也可以看作是一种缓存的变体。常见的诸如JVM,V8这类运行时的常量池、数据库连接池、HTTP连接池、线程池、Golang的sync.Pool对象池等等。在需要某个资源时从现有的池子里直接拿一个,稍作修改或直接用于另外的用途,池化重用也是性能优化常见手段。
【免责声明】本文系本网编辑部分转载,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及作品内容、版权和其它问题,请在30日内与管理员联系,我们会予以更改或删除相关文章,以保证您的权益!请读者仅作参考。更多内容请加抖音太原达内IT培训学习了解。