架构师训练营第五周学习总结
这周的课程是围绕着分布式技术选型展开的,课程由老师解答上周的题目 "一个典型的大型互联网应用系统使用了哪些技术方案和手段" 开始, 带出了本周课程要讨论的缓存技术, 消息队列, 负载均衡和分布式数据库。
总体而言,本周课程的知识密度开始变大,对于我自己而言,技术知识的 "盲区" 和对技术背后原理的掌握上的欠缺开始增多。
本周的知识重点
缓存
什么是缓存: 缓存是介于数据访问者和数据源之间的一种高速存储, 当数据需要多次读取的时候, 用于加快读取的速度。
缓存实现的原理: 使用 Hash 表, 提供快速访问数据的能力。
评估缓存的关键指标: 缓存命中率, 如果查询一个缓存, 十次查询九次能够得到正确的结果, 那么它的命中率是 90%。
影响缓存命中率的主要指标: 缓存键集合的大小、缓存可用空间、缓存对象的生存时间
缓存的读取策略:
通读缓存(read-through): 通读缓存给客户端返回缓存资源, 并在请求未命中缓存时获取实际数据, 客户端连接的是通读缓存而不是生成响应的服务器。
旁路缓存(cache-aside): 对象缓存是一种旁路缓存,旁路缓存通常是一个独立的键值对 (key - value) 存储。应用代码通常会询问对象缓存需要的对象是否存在,如果存在,它会获取并使用缓存的对象,如果不存在或已过期,应用会连接主数据源来组装对象,并将其保存回对象缓存中以便将来使用。
分布式对象缓存的一致性 Hash 算法:
一致性 Hash 算法本质上是一种 Hash 算法, 它会将服务器资源的唯一标识映射到 [0, 2^32 - 1] 的一个段空间中。
一致性 Hash 算法解决的是普通 Hash 算法在服务器集群扩容之后,访问资源定位大量迁移的问题。
一致性 Hash 算法通过引入服务器虚拟节点来解决服务器节点负载不均衡的问题。
各种存储介质访问延迟
操作类型 粗略时间
访问本地内存 100ns
SSD 磁盘搜索 100,000 ns
网络数据包在同一数据中心来回一次的时间 500,000 ns
磁盘搜索(非 SSD) 10,000,000 ns
按顺序从网络读取 1MB 数据 10,000,000 ns
按顺序从磁盘 (非 SSD) 读取 1MB 数据 30,000,000 ns
跨大西洋网络数据包一次来回延时 150,000,000 ns
各技术栈缓存带来的影响
缓存为什么能显著提升性能
缓存通常来源于内存, 比磁盘上的数据有更快的访问速度。
缓存存储数据的最终结果形态,不需要中间计算,减少 CPU 资源消耗。
缓存降低数据库、磁盘、网络的负载压力,使这些 I/O 设备获得更好地响应特性。
一定要合理地使用缓存
使用缓存对提高系统性能有很多好处,但是不合理的使用缓存可能非但不能提高系统的性能,还会成为系统的累赘,甚至风险。
频繁修改的数据: 这种数据如果缓存起来, 由于频繁修改, 应用还来不及读取就已失效或更新, 徒增系统负担。一般来讲,数据的读写比在 2 : 1 以上, 缓存才有意义。
没有热点的访问:缓存使用内存作为存储,内存资源宝贵而有限,不能将所有数据都缓存起来,如果应用系统访问数据没有热点,不遵循二八定律,即大部分数据访问不是集中在小部分数据上,那么缓存就没有意义,因为大部分数据还没有被再次访问就已经被挤出缓存了。
数据不一致与脏读:一般会对缓存的数据设置失效时间,一旦超过失效时间,就要从数据库中重新加载。因此应用要容忍一定时间的数据不一致,如卖家已经编辑了商品属性,但是需要过一段时间才能被买家看到。在互联网应用中,这种延迟通常是可以接收的,但是具体应用仍需谨慎对待。还有一种策略是数据更新时立即更新缓存,不过也会带来更多系统开销和事务一致性的问题。因此数据更新时通知缓存失效,删除该缓存数据,是一种更加稳妥的做法。
缓存雪崩:缓存是为了提高数据读取性能的,缓存数据丢失或者缓存不可用不会影响到应用程序的处理,它可以从数据库直接获取数据。但是随着业务的发展,缓存会承担大部分的数据访问压力,当缓存服务崩溃的时候,数据库会因为完全不能承受如此大的压力而宕机,进而导致整个网站不可用。这种情况,被称作缓存雪崩,发生这种故障,甚至不能简单的重启缓存服务器和数据库服务器来恢复网站访问。
缓存预热:缓存中存放的是热点数据,热点数据又是缓存系统利用 LRU (最近最久未用)算法对不断访问的数据筛选淘汰出来的,这个过程需要花费较长的时间,在这段时间,系统的性能和数据库负载都不好,那么最好在缓存系统启动的时候就把热点数据加载好,这个缓存预加载手段叫做缓存预热。
缓存穿透:如果不恰当的业务、或者恶意攻击持续高并发的请求某个不存在的数据,因为缓存没有保存该数据,所有的请求都会落到数据库上,会对数据库造成很大的压力,甚至崩溃。一个简单的策略是将不存在的数据也缓存起来,并设定一个较短的失效时间。
技术选型上 Redis VS Memcached
Redis 作为缓存的优势
Redis 支持复杂的数据结构
Redis 支持多路复用异步 I/O 高性能
Redis 支持主从复制高可用
Redis 有原生集群与 share nothing 集群模式
Redis 集群的特点
Redis 集群预分好 16384 个桶, 当需要在 Redis 集群中放置一个 key - value 时, 根据 CRC16 (key) mod 16384 的值, 决定将一个 Key 放到哪个桶中。
Redis Cluster 把所有的物理节点映射到[0, 16383] slot 上(不一定是平均分配), cluster 负责维护 slot 与服务器的映射关系。
客户端与 Redis 节点直连,客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
所有的 Redis 节点彼此互联。
消息队列
在互联网系统中引入消息队列构建异步架构的模式为:
消息队列的应用模型主要有:
点对点模型
发布订阅模型
消息队列带来的好处
实现异步处理,提升处理性能:流程异步化之后,不用阻塞业务处理主线程
使系统具备更好地伸缩性:可以根据处理数据量的大小调整消息队列本身和消费者集群的规模
削峰填谷:可以根据消费者的负载能力来处理消息,防止消费者服务因为负载过高而崩溃。
失败隔离和自我修复:因为发布者不直接以来消费者,所以系统消息可以将消费者系统错误与生产者系统组件隔离。生产者和消费者互相不受对方失败影响。
解耦
负载均衡
理想的负载均衡的架构下客户端的流量首先会到达负载均衡服务器,由负载均衡服务器通过一定的调度算法将流量分发到不同的应用服务器上面,同时负载均衡服务器也会对应用服务器做周期性的健康检查,当发现故障节点时便动态的将节点从应用服务器集群中剔除,以此来保证应用的高可用。
Http 重定向负载均衡
HTTP重定向服务器是一台普通的应用服务器,其唯一个功能就是根据用户的HTTP请求计算出一台真实的服务器地址,并将该服务器地址写入HTTP重定向响应中(重定向响应状态码为302)返回给用户浏览器。用户浏览器在获取到响应之后,根据返回的信息,重新发送一个请求到真实的服务器上。
这种负载均衡方案的有点是比较简单,缺点是浏览器需要两次请求服务器才能完成一次访问,性能较差;同时,重定向服务器本身的处理能力有可能成为瓶颈,整个集群的伸缩性规模有限;使用HTTP返回码302重定向,有可能使搜索引擎判断为SEO作弊,降低搜索排名。因此实践中很少使用这种负载均衡方案来部署。
DNS 负载均衡
DNS(Domain Name System)是因特网的一项服务,它作为域名和IP地址相互映射的一个分布式数据库,能够使人更方便的访问互联网。人们在通过浏览器访问网站时只需要记住网站的域名即可,而不需要记住那些不太容易理解的IP地址。在DNS系统中有一个比较重要的的资源类型叫做主机记录也称为A记录,A记录是用于名称解析的重要记录,它将特定的主机名映射到对应主机的IP地址上。如果你有一个自己的域名,那么要想别人能访问到你的网站,你需要到特定的DNS解析服务商的服务器上填写A记录,过一段时间后,别人就能通过你的域名访问你的网站了。DNS除了能解析域名之外还具有负载均衡的功能,每次域名解析请求都会根据对应的负载均衡算法计算出一个不同的IP地址并返回,这样A记录中配置多个服务器就可以构成一个集群,并可以实现负载均衡。
DNS域名解析负载均衡有如下优点:
将负载均衡的工作交给DNS,省去了网站管理维护负载均衡服务器的麻烦。
技术实现比较灵活、方便,简单易行,成本低,使用于大多数TCP/IP应用。
对于部署在服务器上的应用来说不需要进行任何的代码修改即可实现不同机器上的应用访问。
服务器可以位于互联网的任意位置。同时许多DNS还支持基于地理位置的域名解析,即会将域名解析成距离用户地理最近的一个服务器地址,这样就可以加速用户访问,改善性能。
同时,DNS域名解析也存在如下缺点:
目前的DNS是多级解析的,每一级DNS都可能缓存A记录,当某台服务器下线之后,即使修改了A记录,要使其生效也需要较长的时间,这段时间,DNS任然会将域名解析到已下线的服务器上,最终导致用户访问失败。
不能够按服务器的处理能力来分配负载。DNS负载均衡采用的是简单的轮询算法,不能区分服务器之间的差异,不能反映服务器当前运行状态,所以其的负载均衡效果并不是太好。
可能会造成额外的网络问题。为了使本DNS服务器和其他DNS服务器及时交互,保证DNS数据及时更新,使地址能随机分配,一般都要将DNS的刷新时间设置的较小,但太小将会使DNS流量大增造成额外的网络问题。
事实上,大型网站总是部分使用DNS域名解析,利用域名解析作为第一级负载均衡手段,即域名解析得到的一组服务器并不是实际提供服务的物理服务器,而是同样提供负载均衡服务器的内部服务器,这组内部负载均衡服务器再进行负载均衡,请请求发到真实的服务器上,最终完成请求。
反向代理负载均衡
每针对一次代理,代理服务器就必须打开两个连接,一个为对外的连接,一个为对内的连接,因此对于连接请求数量非常大的时候,代理服务器的负载也就非常之大了,在最后反向代理服务器会成 为服务的瓶颈。
IP 负载均衡
运作过程
客户端会向一个ip地址发出请求,这个ip地址是一个
VIP
(虚拟IP),这也是调度器向外公布的一个地址。请求达到调度器,调度器会根据负载均衡算法(详情请见8种负载均衡算法)从
RealServer
列表中选取一个负载不高的服务器,然后把请求报文的目标地址,也就是VIP
和端口通过iptables
进行NAT
转换成选中的服务器的真实ip地址。最后,调度器会把其连接保存在一个hash表中,只要这个连接下次再发请求报文过来就会把其分发到上次选定的服务器中。RealServer
收到报文之后,会把响应返回给调度器。调度器收到报文之后,会把源地址和源端口改为虚拟ip和端口,最后再返回给客户端。
特点
RealServer
和调度器必须位于一个ip网络之中。调度器位于
RealServer
和客户端之间,处理进出的通信。RIP
通常是内部地址,仅用于集群之间通信。RealServer
的网关必须指向调度器。支持端口映射,
RealServer
没必要跟调度器一个端口。
限制
响应报文一般比较大,每一次都需要NAT
转换的话,大流量的时候,会导致调度器成为一个瓶颈。
数据链路层负载均衡
在TCP/IP协议中数据链路层处于最底层,以帧的形式传输和接受数据。在这一层中MAC(Media Access Control)寻址是主要功能。在网络中MAC又称之为MAC地址,用于表示互联网上每个网卡的标识符,采用十六进制表示,共6个字节(48位),烧录在网卡内部。更形象的说MAC地址就像身份证号码,全球唯一。以太网中数据帧之间是通过MAC寻址来到达对应的计算机网卡或者路由的,因此,服务器集群可以充分利用这一特性来进行负载均衡。数据链路层负载均衡通过修改通信协议数据包的 mac 地址进行负载均衡。
这种数据传输方式又称为三角传输,负载均衡数据分发过程中不修改IP地址,只修改目的MAC地址,通过配置真实物理服务器集群所有机器虚拟IP和负载均衡服务器IP一致,从而达到不修改数据包的源地址和目的地址就可以进行数据分发的目的,由于实际处理请求的真实物理服务器IP和数据请求目的IP一致,不需要通过负载均衡服务器进行地址交换,可将响应数据包直接返回给用户浏览器,避免负载均衡服务器网卡带宽成为瓶颈。
负载均衡算法
轮询法
将请求按顺序轮流地分配到后端服务器上,它均衡地对待后端的每一台服务器,而不关心服务器实际的连接数和当前的系统负载。
随机法
通过系统的随机算法,根据后端服务器的列表大小值来随机选取其中的一台服务器进行访问。由概率统计理论可以得知,随着客户端调用服务端的次数增多,
其实际效果越来越接近于平均分配调用量到后端的每一台服务器,也就是轮询的结果。
源地址哈希法
源地址哈希的思想是根据获取客户端的IP地址,通过哈希函数计算得到的一个数值,用该数值对服务器列表的大小进行取模运算,得到的结果便是客服端要访问服务器的序号。采用源地址哈希法进行负载均衡,同一IP地址的客户端,当后端服务器列表不变时,它每次都会映射到同一台后端服务器进行访问。
加权轮询法
不同的后端服务器可能机器的配置和当前系统的负载并不相同,因此它们的抗压能力也不相同。给配置高、负载低的机器配置更高的权重,让其处理更多的请;而配置低、负载高的机器,给其分配较低的权重,降低其系统负载,加权轮询能很好地处理这一问题,并将请求顺序且按照权重分配到后端。
加权随机法
与加权轮询法一样,加权随机法也根据后端机器的配置,系统的负载分配不同的权重。不同的是,它是按照权重随机请求后端服务器,而非顺序。
最小连接数法
最小连接数算法比较灵活和智能,由于后端服务器的配置不尽相同,对于请求的处理有快有慢,它是根据后端服务器当前的连接情况,动态地选取其中当前积压连接数最少的一台服务器来处理当前的请求,尽可能地提高后端服务的利用效率,将负责合理地分流到每一台服务器。
总结
进入分布式篇章的课程后, 知识密度开始变大, 对于网络的知识有所欠缺。通过学习,各种架构方案的使用场景和利弊的掌握得到了提升。
评论