后端面试38讲_25_22_缓存架构如何减少不必要的计算
你好,我是李智慧。
上一篇我们讲到互联网应用的主要挑战呢,就是在高并发的情况下,大量的用户请求到达应用系统服务器,造成巨大的计算压力。
互联网应用的核心解决思路就是采用分布式架构,提供更多的服务器,从而提供更多的计算资源,以应对高并发带来的计算压力以及资源消耗。
那么有没有办法减少到达服务器的并发请求压力呢?或者请求到达服务器以后,有没有办法减少不必要的计算,降低服务器的计算资源消耗,尽快返回结果给用户呢?这样解决的核心就是缓存。
所谓缓存,就是将需要多次读取的数据暂存起来。
这样后面应用程序需要多次读取的时候,就不必从数据源重新加载数据了。
这样就可以降低数据源的计算负载压力,提高数据响应的速度。
一般说来,缓存可以分成两种,通读缓冲和旁络缓存,通读缓存应用程序访问通读缓冲获取数据的时候,如果通读缓冲由应用程序需要的数据,那么就返回这个数据。
如果没有,那么同读缓冲,就自己负责访问数据源,从数据源获取数据返回给应用程序,并将这个数据缓冲在自己的缓冲中。
这样下次应用程序需要数据的时候,就可以通过通读缓冲直接获取数据了。
你在文稿中可以看到通透缓冲在架构中的位置与作用的示意图。
旁路缓冲应用程序访问旁路缓冲获取数据的时候,如果旁路缓冲中有应用程序需要的数据,那么就返回这个数据。
如果没有,就返回空应用程序,需要自己从数据源读取数据,然后将这个数据写入到旁路缓冲中。
这样下次应用程序需要读取数据的时候,就可以通过旁路缓冲直接获得数据了。
同样的旁路缓冲在架构中的位置与作用的示意图也在文章中。
互联网应用中主要使用的同路缓冲是CDN和反向代理缓冲CDN,也就是内容分发网络。
我们上网的时候,APP或者浏览器想要连接到互联网应用的服务器,需要网络服务商,比如移动、电信这样的网络服务商,为我们提供网络服务,建立网络连接才可以上网。
而这些服务商需要在全国范围内部署骨干网络交换机机房才能够完成网络连接服务。
这些交换机机房可能会离用户非常近。
那么,互联网应用能不能在这些交换机机房中部署缓冲服务器呢?这样用户就可以就近获得自己需要的数据。
既提高了响应的速度,又节约了网络带宽和服务器的资源。
当然可以了,这个部署在网络服务商机房中的缓存就是CDN.因为距离用户非常近,又被称作网络连接的第一跳。
目前很多互联网应用大约百分之八十以上的网络流量都是通过cdn返回的。
Cdn只能够缓存静态数据内容,比如图片CSSGSATML内容容而态的内容,比如订单查查询、商品搜索结果等,必须要应用服务器进行计算后能能获得。
所以,互联网应用的静态内容和动态内容需要进行服务,离静态内容和动态内容部署在不同的服务器集群上使用不同的二级域名及所谓的动态分离。
一方面便于用位管理,另一方面也便于CDN进行缓存,使CDN只缓存进台上。
反向代理缓存也是一种通过缓存。
我们上网的时候,有时候需要通过代理上网,这个代理就是代理我们客户端上网设备。
而反向代理则是代理服务器,使应用服务器的门户。
所以网络请求都需要通过反反服代理才能够到达应用服务器。
既然所有的请求都需通过反向代理才能够到达应用服务器,那么在这里就可以加一个缓存,尽快将数据返回给用户,而不是发送给应用服务器。
这就是反向代理缓冲用户,请求到达反向代理缓冲服务器,反向代理检查本地是不是有需要的数据。
如果有,就直接返回。
如果没有,就请求应用服务器得到需要的数据后缓冲在本地,然后返回给用户CDN和反向代理。
缓冲通常会作为系统架构的一部分,很多时候对应用程序是透明的。
而应用程序在代码中主要使用的是对象缓冲,对象缓冲是一种旁路缓冲,不管是通读缓冲还是旁路缓冲,缓冲通常都是以k value的方式存储在缓冲中,比如CDN和反向代理缓冲中,每个URL是一个k那么UIL对应的文件内容就是value.而对象缓冲中k通常是一个ID,比如用户id商品ID等等。
而value只是一个对象,就是id对应的用户对象或者是商品对象。
对于开value的数据格式,我们前面在数据结构讨论过,比较快速的冲取方式就是使用哈希表。
因此,通度缓冲和旁络缓冲在实现上基本上用的都是哈希表程序中使用的对象。
缓冲可以分成两种,一种是本地缓冲。
缓冲和应用程序在同一个进程中启动使用程序的堆空间存放缓冲数据。
本地缓冲的响应速度快,但是缓冲可以使用的内存空间相对比较小。
但是对于大型的互联网应用所学的缓冲数据,通常以t级这时候就要使用远程的分布式缓冲呢。
分布式缓冲是指将一组服务器构成一个缓冲集群,共同对为提供缓存服务。
那么应用程序在每次读写缓冲的时候,如何知道要访问集群中的哪一台服务器呢?我们以MMKHD为例,看一看分布式缓冲的架构,MMMKHD将多台服务器构成一个缓冲集群缓冲数据,用远在每台服务务器的内存中。
事实上,使用缓冲的应用程序服务器通常也是以集群方式部署的,每个程序需要依赖一个MMKHD的客户端。
Sdk通过这个SDK的API访问MMKHD的服务器应用程序调用IHIAPI调用SDK的路由算法,路由算法根据缓冲的k值计算,这个k应该访问哪台? Mmkhd服务器计算得到服务器的IP地址和端口号。
Api再调用SDK的通讯模块,将k value值以及缓冲命令发送给具体的某台MMKHD服务器由这台缓冲服务器完成缓冲操作。
那么,路由算法又是如何计算得到MMKHD的服务器?Ip和端口呢?比较简单的一种方法和哈希算法一样,利用k的哈希值对服务器的列表长度器模,根据余数就可以确定服务器IP的下标,进而得到服务器的IP和端口。
利用缓冲可以减少不必要的计算,能够带来三个方面的好处。
一、缓冲的数据通常存储在内存中距离使用,数据的应用也更近一点。
因此,相比从硬盘上获取或者从远程网络上获取,它获取数据的速度更快一点,可应速度更快。
性能表现更好。
二、缓冲的数据通常是计算结果数据,比如对象。
缓冲中通常存放经过计算加工的结果,对象如果缓冲不命中,那么就需要从数据库获取原始数据,然后进行计算加工才能得到结果。
对象。
因此,使用缓冲可以减少CPU的计算消耗,节省计算资源,同样也加快了处理的速度。
三、通过对象缓冲获取数据,可以降低数据库的负载压力。
通过CDN、反向代理等。
通过缓冲获取数据可以降低服务器的负载压力。
这些被释放出来的计算资源可以提供给其他更有需要的计算场景。
比如显数据的场景,间接的提高了整个系统的处理能力。
但是缓存也不是万能的,如果不恰当的使用缓存也可能会带来问题。
首先就是数据张度的问题,缓冲的数据来自数据源。
如果数据源中的数据被修改了,那么缓冲中的数据就变成了脏数据了。
主要的解决办法有两个,一个是过期失效。
每次写入缓冲中的数据都标记其时效时间。
在读取缓冲的时候呢,检查数据是否已经过期失效,如果失效了,就重新从数据源获取数据缓冲失效,依然可能会在未失效的时间内读到脏数据。
但是一般的应用都可以容忍较短时间的数据不一致。
比如淘宝卖家更新了商品信息,那么几分钟的数据没有更新到缓存。
热家看到的还是旧数据,这种情况下通常是可以接受的,这个时候就可以设置缓冲时效的时间为几分钟。
另一个办法是失品信息应用程序更新数据源的数据同时发送通知,将该数据从缓冲中清除掉时效通知看起来数据更新的更加及时。
但是在实践中呢更多使用的还是过期时效。
此外,并不是所有的数据使用缓冲都有意义。
在互联网应用中,大多数数据访问都是有热点的。
比如热门的微博会被更多的阅读,热门的商品会被更多的浏览。
那么将这些热门的数据保存在缓冲中是有意义的。
因为缓冲通常使用内存存储空间比较有限,只能存储有限的数据热门数据存储在缓冲中可以被更多次的读取,缓冲效率使用也比较高。
相反,如果缓冲的数据没有热点,写入缓冲的数据很难被重复读取,那么使用缓冲就不是很有必要了。
缓冲使优化软件性能的杀手锏,任何需要查询数据请求数据的场合都可以考虑使用缓冲。
缓冲几乎是无处不在的程序架构中可以使用缓冲,网络架构中可以使用缓冲CPU操作系统虚拟机也大量的使用缓冲。
事实上,缓冲最早就是在CPU中使用的。
对于一个典型的互联网应用而言,使用缓冲可以解决大部分的性能问题。
如果需要优化软件性能,那么可以优先考虑哪里可以使用缓冲改善性能。
除了本篇提到的系统架构缓冲外,客户端也可以使用缓冲,在APP或者浏览器中缓冲数据,甚至都不需要消耗网络带宽资源,也不会消耗CDN反向代理的内存资源,更不会消耗数据中心的服务器的计算资源。
我们讲MMKHD路由算法时讲到使用榆速哈希算法,但是语数哈希算法在MMKHD服务器集群扩容,也就是增加服务器的时候会遇到较大的问题。
问题是什么呢?应该如何解决?欢迎你在评论区写下你的思考,也欢迎把这篇文章分享给你的朋友,或者同事一起交流进步一下。