架构师训练营第五周课后总结

发布于: 2020 年 07 月 07 日

本周主要内容:分布式缓存、异步、负载均衡

分布式缓存

缓存是介于数据访问者和数据源之间的一种高速存储,当数据需要多次读取的时候,用于加快数据读取的速度。

电脑的硬件分为硬盘、CPU、内存,CPU的速度是非常快的,而硬盘因为设计结构,需要进行寻址、文件IO的操作导致硬盘的速度比起CPU来说是大大不如的,所谓CPU操作的数据如果直接操作硬盘,将因为硬盘的速度低下而拖慢计算机整体的计算速度,所以为了提升效率,就会为CPU提供高速缓存,这种高速缓存还存在级别,通常越接近CPU的那一级,读写速度越快,但成本也越高,所以这种高速缓存在计算机中都比较小,能满足CPU的计算即可。

而内存也是一种数据存储,他也是为了提升数据读取效率而设计,有CPU的这种设计思路,那么是不是可以把原本数据访问者每次都要从硬盘读取的数据提前加载到内存中,从而提升数据访问效率呢?

缓存应运而生,缓存普遍都是应用内存来实现的,因为内存的读取效率更高,这个内存可能是程序为我们提供的内存,例如JVM本地缓存,也有可能是外部应用为我们提供的,例如redis和memcached。无论哪种,查询效率都不是硬盘直接读取可比的,但内存不是无限大的,内存也远比硬盘昂贵的多,如何合理利用和设计缓存系统就是我们架构师需要考虑的了。

应用缓存的方式被设计出了很多方式,总体分为两类:通读缓存和旁路缓存。

  • 通读缓存

通读缓存是对数据访问者来说,A向B请求数据,B做查询数据时,优先在缓存区查询,查询不到则从远端服务器上查询数据,远端服务器返回后在缓存在本地,下次查询时从A获取。则这个缓存对于A来说就是通读缓存。

代理缓存、方向代理缓存、CDN缓存都是属于通读缓存。

  • 旁路缓存

还是上面的例子,但看待的角度改变一下,这个数据针对B来说就是旁路缓存。

缓存是提高系统性能的大杀器,而如何利用好缓存也就是重点。

设计缓存的目的就是为了不让请求访问到数据库这一层,所以缓存问题的三连问也是面试喝设计常见问题:

  • 缓存雪崩

缓存雪崩通常是由于大量缓存失效而导致大量请求访问数据库,造成的雪崩响应。解决这种问题首先是要明确缓存失效的原因是什么,比如由于缓存失效时间设置一致,导致大量缓存同时失效,造成雪崩,这种问题通常可以在缓存失效时间后加一个随机时间,让缓存失效时间均匀分散开。

还有一种是缓存集群扩容导致很多缓存失效,这种通常是需要对缓存进行预热,再进行扩容。

  • 缓存穿透

缓存穿透是指有心人一直访问一个不存在的数据,从而一直访问数据库。这种可以对这种不存在的key缓存一个空值,从而避免穿透而打库,还有一种是利用布隆过滤器,识别出这种数据库不存在的key从而防止缓存穿透。

  • 缓存击穿

缓存击穿是指一个热点数据突然失效,导致大量请求访问到数据库。这种问题可以从两个角度来解决。

一个角度是把这些大量的请求拦截住,只放一个请求去访问数据库,访问到后放入缓存,再让这些请求从缓存读取。

另外一种是对这种热点缓存单独维护,可以让缓存不失效,定期更新这个热点缓存,本身热点缓存也应该是作为单独维护的。比较起来其实第二个方案虽然更麻烦,但对系统的性能来说还是更优秀的。

以上对缓存的设计更多是一个数据作为缓存应该如何设计,而哪些数据适合作为缓存呢?一般而言,缓存空间是比硬盘空间小的多,这就代表我们需要对缓存的数据有一个选择,而一个重要的指标也用于做这种判断,缓存的命中率,通常来讲,读多写少的场景命中率更高,而那些读多写多或者读少写多或者读少写少的都不太适合做缓存,一方面读多写多的场景缓存经常失效,导致无法命中缓存,另一方面,读少写多或者读少写少的场景,本身读的就比较少,这部分缓存意义也比较小。

异步

在工作中总会有这样的业务场景,在一些主干业务上总会在某些节点增加一些分支业务,这些分支业务没有实时性要求,也不关心执行结果,只要能执行即可。

还有一种场景,用户访问的是主干业务,但这个业务逻辑很复杂,而且用户也不关心执行结果,只要最终执行成功即可。

以上两种场景都是非常适合异步的,而异步有在本地开一个线程异步执行的方式,但是这种方式如果出现机器宕机重启还是可能会业务失败,所以使用异步消息队列的方式更方便,主干分支只要在合适的时间点发出事件消息,然后分支业务监听消息队列,对自己感兴趣的事件做出响应即可,而对于主干来说只要保证消息成功发送给消息中间件即可。

另外下面第二种场景同理,使用消息中间件,实现最终一致。

异步消息一方面可以削峰填谷,另一方面可以实现业务解耦。

负载均衡

  • http重定向负载均衡

这种负载均衡的方式是用户访问到http服务,然后http服务应用负载均衡算法重定向到一台应用机器,这种方式是性能和体验都不太好,所以这种方式一般很少使用

  • DNS负载均衡

这种方式是客户端负载均衡,用户在根据域名进行dns解析时会应用负载均衡算法,可能是轮询或者根据地区返回不同的ip地址,从而请求后端不同的服务器,这种负载均衡方式一般是搭配其他服务器负载均衡方式来使用的。服务器端提供多个负载均衡服务器,然后dns对这多个负载均衡服务器进行dns负载均衡。

  • 反向代理负载均衡

反向代理负载均衡通常是应用一个负载均衡服务器,用户请求负载均衡服务器,这个服务器应用负载均衡算法找出一台应用服务器,然后将请求透传到其他应用服务器。

这种反向代理的负载均衡通常跟用户请求协议有关,如果用户请求是在7层,那么反向代理服务器也是工作在7层,如果用户请求是在4层,那么反向代理服务器也是工作在4层。

比较常用的反向代理服务器有nginx和haproxy。这两种都支持4层代理和7层代理。

一般小型公司都会使用这种方式做负载均衡,不过这种方式在大公司应用也还是有缺点的,因为工作在7层,就代表一定会解析http协议,但实际上解析出来的信息对代理服务器来说没有意义,只是为了继续向后传递,而这个解析过程也就是性能损耗点了,同时因为流量都是走反向代理服务器流入流出,该服务器的性能也会受到机器网卡的限制。

  • IP负载均衡

ip层负载均衡工作在IP层,他不关心上层协议,也不会解析上层协议,他只是把请求中的目的地ip和源地址做修改让请求去到正确的地方,这个方式避免了对协议解析带来的性能损耗,但是因为还是单机流入流出,性能还是受到网卡限制。

  • 数据链路层负载均衡

数据链路层负载均衡解决了以上问题,他修改的不再是ip地址,而是mac地址,因为负载均衡服务器和后端应用服务器使用了相同的ip,修改mac地址后,请求正确流入到应用服务器,应用服务器处理数据后直接将数据返回给用户端,而不必经过负载均衡服务器返回,也就不再受到负载均衡服务器网卡的限制。

以上的负载均衡策略都应当是在架构演进中逐渐选择适合的方式,或者某些方式的组合。

发布于: 2020 年 07 月 07 日 阅读数: 9
用户头像

Cloud.

关注

还未添加个人签名 2020.05.14 加入

还未添加个人简介

评论

发布
暂无评论
架构师训练营第五周课后总结