当前位置: 首页 > 科技观察

解决系统性能问题的灵丹妙药---缓存技术

时间:2023-03-21 19:35:13 科技观察

仔细看看我们现有的系统,小到一个CPU,大到一个在线交易系统。任何性能问题都可以通过一种方式有效解决,这种方式就是缓存。是的,缓存几乎可以成为解决性能问题的灵丹妙药,而且会一针见血。缓存的主要目的是减少数据访问延迟,有多种实现方式。以下是对不同类型缓存的介绍。CPU的缓存能想到的最小粒度的缓存大概就是CPU的缓存了。CPU不仅有缓存,还把缓存分为多级,如图1所示,分别是L1、L2、L33级缓存。其中,L1和L2是一个核心独享的缓存,而L3是同一个CPU中的多个核心共享的。图1中的架构是目前CPU中最常见的架构,CPU缓存的架构细节比这更复杂。大多数CPU将缓存分为指令缓存和数据缓存2,有的还有一个叫做TLB(translationlookasidebuffer)的缓存,用于实现虚拟内存到物理内存的快速转换。图1CPU缓存架构CPU并不是天生就有缓存的。以Intel的CPU为例,1992年才在386CPU中引入L1Cache,直到2008年Corei3才引入L3Cache。图2显示了不同存储类型访问延迟的差异。以寄存器访问为一个时间单位,内存访问约为100个单位。也就是说,内存访问延迟是寄存器的100倍。图2不同存储访问性能对比基于以上原因,新一代CPU设计中加入了缓存模块,目的是降低访问内存数据的延迟。使用Cache提高性能的原理在于数据访问的局部性,即区域局部性和时间局部性。空间局部性:对于刚被访问过的数据,相邻的数据未来被访问的概率很高。TemporalLocality:对于刚被访问过的数据,未来被访问的概率很高。操作系统缓存缓存在操作系统级别的许多地方使用。操作系统缓存的原理与CPU缓存基本相同,只有两个局部特征。操作系统中最好的缓存可能是文件系统的页面缓存。再参考图2,可以看出访问磁盘的延迟是内存的10万倍,所以Linux操作系统中的所有文件系统都使用缓存来提高读写性能。除了上述内存访问性能和磁盘访问性能的差异外,还有一个因素是机械磁盘随机访问和顺序访问的性能差异。以企业级SATA盘为例,随机写入带宽不足1MB/s,而顺序写入则轻松达到100MB/s,相差高达100倍。造成如此大差异的主要原因是机械盘读写数据需要寻址,而寻址消耗的时间占整个请求时间的很大比例。考虑到以上两个因素,大多数文件系统都实现了基于内存的缓存。这样,大大提高了用户对文件系统的访问性能。缓存主要从两个方面提高访问文件系统的性能。一是减少对磁盘的直接访问,二是尽可能将对磁盘的随机访问转化为顺序访问。对于第一个方面,文件系统数据写入缓存后,认为数据写入成功,将结果返回给上层。因为访问内存的性能是访问磁盘的10万倍。因此,性能自然可以得到很大的提升。如图3上半部分逻辑所示,写请求顺序将数据写入缓存。读取请求也有类似的过程。在文件系统中,称为预读,即提前将数据读入缓存,从而降低访问磁盘的频率。图3文件系统页缓存对于第二个方面,由于缓存的存在,当数据从缓存刷入磁盘时,数据的LBA是经过排序的。这样可以降低机械寻盘的耗时比,从而提高系统的整体性能。大系统级别的Web前端缓存我们以Web应用为例,介绍从前端到后端的缓存技术。这主要是因为缓存在web开发领域应用最为广泛,非常方便我们理解问题。缓存的技术领域很广,技术难度也很深。本文不能面面俱到,抛砖引玉。熟悉前端开发的同学都知道,一个网站除了动态内容之外,还有很多图片、JS脚本、CSS示例等内容。一方面是图片、JS脚本、CSS等内容比较多,另一方面很少变动,除非网站升级。鉴于以上原因,我们能否将内容缓存到用户的本地磁盘,这样当用户再次访问网站时,可以直接从本地磁盘加载内容,而不需要经过浩瀚的网络。图4浏览器页面请求本质上,浏览器已经具备了这个功能。准确的说,它不是浏览器,而是HTTP协议。如图所示,我们打开浏览器的调试工具,可以看到请求的网页很多内容并不是向服务器请求的,而是从本地磁盘或者内存中获取的。图4显示了请求网站页面时部分内容的情况。可以看出,很大一部分不是从服务器获取的。图5Web浏览器缓存处理流程本地获取有两个非常明显的好处。一是页面的响应时间非常快,二是大大减轻了Web服务器的压力。在HTTP中,通过它的响应头来决定是否使用缓存中的内容。这个header就是Cache-control,当然需要其他域的配合。整个缓存处理过程比较复杂,需要根据不同的字段进行判断,才能确定从哪里获取内容。图中展示了整个浏览器的处理流程。图6是浏览器调试工具截获的某网站首页图片的响应头内容。从图中可以看出,它包含了缓存控制相关的内容。图6Web缓存的HTTP协议浏览器缓存的内容博大精深,本文难以详尽阐述。如果你想深入了解这方面的内容,本账号推荐你阅读《HTTP权威指南》,讲解的很详细。访问链接级别在web领域,一个请求的链接可能会很长。比如我们在美国访问一个网站,整个通信链路会跨越整个太平洋,距离将近两万公里。就算是太阳,也要跑几十毫秒才能跑完这个里程,而网络需要经过各种中继设备,耗时将近200毫秒。试想一下,一个网页通常由上百个元素(如图片、js脚本等)组成,那么在中国打开一个美国网站需要多少时间呢?解决上述问题最有效的技术是CDN(ContentDeliveryNetwork,内容分发网络)技术,它通过分支到更接近终端用户的边缘服务器来提供更快的服务。以上述网站为例,当用户从中国访问美国网站时,会先从国内的CDN节点获取内容,如果没有,则从美国的源服务器获取内容。因为大部分内容都可以在国内获取,消除了跨越大洋带来的网络延迟。图7CDN示意图图7为CDN示意图,其中ORIGINALSERVER为源服务器,EDGESERVER为边缘服务器。从图中可以看出,最终用户的访问路径。对于Web服务,Web后端缓存通常通过关系数据存储数据,而数据库数据通常存储在磁盘上。数据库在高负载场景下容易成为性能瓶颈。因此,为了提高整个服务的承载能力,往往会在业务服务器和数据库之间加入缓存服务。这个缓存服务的原理其实和上面说的CPU缓存或者文件系统缓存类似。由于对于一个Web服务来说,80%以上的请求都是读请求,Web缓存的设计就是基于这个事实。这些数据可以完全缓存在内存中,从而减少数据库访问的负载。由于缓存承载了大部分的读请求,整个数据库的负载也大大降低。图8Web服务缓存图8显示了使用Redis缓存的Web服务架构。本文只是一个简化的架构,实际的架构要复杂得多(需要考虑可靠性和承载能力)。在该架构中,业务服务器会根据请求类型优先访问缓存,并根据策略更新缓存内容。目前使用最多的缓存应该是Redis缓存了,大家可以多了解一下。本文从微观到宏观,从不同层面介绍缓存在提升系统性能方面的应用。当然,缓存的应用领域比本文所涵盖的要多得多。这里只是介绍一下,希望能给大家带来一些启发,为自己系统的性能优化提供一些思路。