极客时间架构师培训 1 期 - 第 5 周总结

用户头像
Kaven
关注
发布于: 2020 年 10 月 25 日
分布式缓存,主要针对读的性能优化



  • 缓存的概念

缓存:存储在计算机上的一个原始数据复制集,以便于访问–维基百科

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

CPU缓存

操作系统缓存

数据库缓存

JVM编译缓存

CDN缓存

代理与反向代理缓存

V8引擎编译缓存

前端缓存

应用程序缓存

分布式对象缓存

  • 缓存的关键指标

缓存命中率

  • 影响缓存命中率的主要指标

缓存键集合大小 - 缓存中的每个对象使用缓存键进行识别,定位一个对象的唯一方式就是对缓存键执行精 确匹配;一定要想办法减少可能的 缓存键数量。键数量越少,缓存的效率越高。

缓存可使用内存空间 - 缓存可使用内存空间直接决定了缓存对象的平均大小和缓存对象数量。因为缓存通常存 储在内存中,缓存对象可用空间受到严格限制且相对昂贵。如果想缓存更多的对象,就 需要先删除老的对象,再添加新的对象。替换(清除)对象会降低缓存命中率,因为缓存对 象被删除后,将来的请求就无法命中了。物理上能缓存的对象越多,缓存命中率就越高。

缓存对象生存时间 - 缓存对象生存时间称为TTL(Time To Live )。在某些场景中,例如,缓存天气预报数 据15 分钟没问题。在这个场景下,你可以设置缓存对象预定义TTL 为15 分钟。在其他场景中,你可能不能冒险使用过于陈旧的数据。例如,在一个电子商务系统中,店铺 管理员可能在任何时刻修改商品价格,如果这些价格需要准确地展示在整个网站中(写操作)。在这个场景下,你需要在每次商品价格修改时让缓存失效。简单讲,对象缓存的时间越长, 缓存对象被重用的可能性就越高

  • 主要的缓存方式

代理缓存,如代理上网

反向代理缓存

多层反向代理缓存

内容分发网络(CDN)

CDN同时配置静态文件与动态内容

  • 通读缓存(READ-THROUGH)

代理缓存,反向代理缓存,CDN缓存都是通读缓存。

通读缓存给客户端返回缓存资源,并在请求未命中缓存时获取实际数据。

客户端连接的是通读缓存而不是生成响应的原始服务器。

  • 旁路缓存(cache-aside)

对象缓存是一种旁路缓存,旁路缓存通常是一个独立的键值对(key-value)存储。

应用代码通常会询问对象缓存需要的对象是否存在,如果存在,它会获取并使用缓存 的对象,如果不存在或已过期,应用会连接主数据源来组装对象,并将其保存回对象缓存中以便将来使用。

  • 浏览器对象缓存

在WebStorage中缓存对象的JavaScript代码

  • 本地对象缓存

对象直接缓存在应用程序内存中。

对象存储在共享内存,同一台机器的多个进程可以访问它们。

缓存服务器作为独立应用和应用程序部署在同一个服务器上

  • 本地对象缓存构建分布式集群

缓存之间互相同步

  • 远程分布式对象缓存

  • 分布式缓存的一致性hash算法,与余数hash算法区别

余数hash算法: 缓存分布不均衡;不利于弹性伸缩,容易造成服务宕机;

一致性hash算法:便于动态扩容

基于虚拟节点的一致性Hash算法

  • 分布式缓存分片模式

客户端分片:通过应用直接操作分片逻辑,性能好,实现简单,有问题时容易定位与修复。但应用服务连接缓存服务器增多,需要做好容量评估。

代理分片:在应用层与服务层增加一个代理层,由代理层对外提供接口给应用层。开发人员只关注业务逻辑即可。但需要做好分片的路由规则,性能有影响,维护成本高(软硬件成本,专业运维人员)

集群分片:可以实现分片与高可用特性。我们只需要把集群当成一个由多个服务器节点组成的大缓存机器来使用即可。分片与高可用对应用层透明。

  • 分布式缓存迁移方案

平滑迁移 - 具体步骤:双写,迁移历史数据,切读,下双写

停机迁移 - 停止应用,迁移历史数据,更改应用的数据源,启动应用

一致性哈希

  • 分布式缓存设计的核心要素

存量规划

性能优化

高可用

缓存监控

  • 各种介质数据访问延迟



| 操作类型 | 粗略时间 |

| -------------------------------------- | ------------- |

| 访问本地内存 | 100ns |

| SSD磁盘搜索 | 100000ns |

| 网络数据包在同一数据中心来回一次的时间 | 500000ns |

| 磁盘搜索(非SSD) | 10000000ns |

| 按顺序从网络读取1mb数据 | 10000000ns |

| 按顺序从磁盘(非ssd)读取1mb数据 | 30000000ns |

| 跨大西洋网络数据包一次来回延迟 | 150000000ns |

| 每秒等于多少 | 10 00000000ns |



  • 技术栈各个层次的缓存



  • 缓存为什么能显著提升性能(读)

缓存数据通常来自内存,比磁盘上的数据有更快的访问速度。

缓存存储数据的终结果形态,不需要中间计算,减少CPU资源的消耗。

缓存降低数据库、磁盘、网络的负载压力,使这些I/O设备获得更好的响应特性。

  • 缓存是系统性能优化的大杀器

技术简单

性能提升显著

应用场景多

  • 缓存应用

使用缓存对提高系统性能有很多好处,但是不合理的使用缓存可能非但不能提高系统的 性能,还会成为系统的累赘,甚至风险。实践中,缓存滥用的情景屡见不鲜——过分依赖缓存、不合适的数据访问特性等

频繁修改的数据:这种数据如果缓存起来,由于频繁修改,应用还来不及读取就已失效或更新,徒增系统负担。一般说来,数据的读写比在2:1以上,缓存才有意义。

没有热点的访问:缓存使用内存作为存储,内存资源宝贵而有限,不能将所有数据都缓存起来,如果应用系统访问数据没有热点,不遵循二八定律,即*大部分数据访问不是集中在小部分数据上,那么缓存就没有意义*,因为大部分数据还没有被再次访问就已经被挤出缓存了

数据不一致与脏读:一般会对缓存的数据设置失效时间,一旦超过失效时间,就要从数据库中重新加载。因此应用要容忍一定时间的数据不一致,如卖家已经编辑了商品属性, 但是需要过一段时间才能被买家看到。在互联网应用中,这种延迟通常是可以接受的, 但是具体应用仍需慎重对待。还有一种策略是数据更新时立即更新缓存,不过也会带来更多系统开销和事务一致性的问题。因此数据更新时通知缓存失效,删除该缓存数据,是一种更加稳妥的做法



“计算机科学中只有三件事困难:缓存失效,命名事物,计数错误。” ——Phil Karlton




缓存雪崩:缓存是为了提高数据读取性能的,缓存数据丢失或者缓存不可用不会影响到应用程序的处理,它可以从数据库直接获取数据。但是随着业务的发展,缓存会承担大 部分的数据访问压力,数据库已经习惯了有缓存的日子,所以当缓存服务崩溃的时候, 数据库会因为完全不能承受如此大的压力而宕机,进而导致整个网站不可用。这种情况, 被称作缓存雪崩,发生这种故障,甚至不能简单的重启缓存服务器和数据库服务器来恢 复网站访问。

缓存预热:缓存中存放的是热点数据,热点数据又是缓存系统利用LRU(近久未用) 算法对不断访问的数据筛选淘汰出来的,这个过程需要花费较长的时间,在这段时间, 系统的性能和数据库负载都不太好,那么好在缓存系统启动的时候就把热点数据加载好,这个缓存预加载手段叫做缓存预热(warm up)。对于一些元数据如城市地名列表、 类目信息,可以启动时加载数据库中全部数据到缓存进行预热

缓存穿透:*如果不恰当的业务、或者恶意攻击持续高并发的请求某个不存在的数据,因 为缓存没有保存该数据,所有的请求都会落到数据库上,会对数据库造成很大的压力, 甚至崩溃。*一个简单的对策是将不存在的数据也缓存起来(其value值为null),并设定一个较短的失效时间。 还有采用布隆过滤器等方式。

缓存并发:高并发场景:当一缓存过期时,因为访问这个缓存请求量大,多个请求发现缓存失效,会同时访问数据库查询最新数据,并回写缓存,这样会造成应用于数据库的负载增加,性能降低,甚至会压垮数据库。通常通过分布式锁(限制只有一个线程访问后端服务),本地锁(限制本地只有一个线程访问数据库),软过期(启动一个线程的,定期刷新缓存)

  • 应用访问缓存的模式

双读双写:在应用层的业务逻辑中同时进行缓存的读写操作;耦合

异步更新:异步,独立更新操作缓存;性能好,应用读缓存即可;

串联模式:应用直接在缓存上操作,缓存作为代理层,根据需要与配置与数据库进行读写操作。

  • Redis VS Memcached

Redis是基于Memcached基础上优化开发出来

Redis支持复杂的数据结构

Redis支持多路复用异步I/O高性能

Redis支持主从复制高可用

Redis原生集群与sharenothing集群模式,Memcached只支持sharenothing模式

  • Redis高可用方案

哨兵模式

redis集群

  • Redis集群

Redis集群预分好16384个桶,当需要在 Redis集群中放置一个key-value 时,根据 CRC16(key) mod 16384的值,决定将一个 key放到哪个桶中。

redis-cluster把所有的物理节点映射到[016383]slot上(不一定是平均分配), cluster 负责维护slot与服务器的映射关系。

客户端与Redis节点直连,客户端不需要连 接集群所有节点,连接集群中任何一个可用 节点即可。

所有的Redis节点彼此互联。

消息队列, 主要是针对写的性能优化
  • 同步调用与异步调用

同步调用:耗时,吞吐量低,影响性能。

异步调用:可回调,不阻塞应用线程。并发量大,吞吐量高,应用性能稳定,可用性高。

  • 消息队列元素:消息生产者,消息队列,消息消费者

  • 消息队列模式

点对点模型:一个消息只能有一个消费者可消费;且不能多次消费

发布订阅模型:一个消息可被多个消费者多次消费。

  • 消息队列好处

1. 实现异步,提高处理性能。

2. 更好的伸缩性。

3. 削峰填谷,应用负载压力稳定,高可用;

4. 失败隔离与自我修复,生产者与消费者互相不受对方失败影响,任意时刻,我们都可以对后端服务器执行维护和发布操作。我们可以重启、添 加或删除服务器而不影响生产者可用性,这样简化了部署和服务器管理的难度。

5. 解耦,生产者与消费者代码互相独立,不用对方都在做什么

  • 事件驱动架构 EDA

  • 主要MQ产品比较

产品选型需考虑:1. 业务场景;2. 产品的社区活跃程度,成熟度,受众关注程度;

1. RabbitMQ 的主要特点是性能好,社区活跃,但是RabbitMQ用Erlang开发,对不熟 悉Erlang的同学而言不便于二次开发和维护。(49M)

2. ActiveMQ 影响比较广泛,可以跨平台,使用Java开发,对Java比较友好。(27M)

3. RocketMQ是阿里推出的一个开源产品,也是使用Java开发,性能比较好,可靠性也 比较高。(35M)

4. Kafka ,LinkedIn出品的,Scala开发,专门针对分布式场景进行了优化,因此分布 式的伸缩性会比较好。(63M)




负载均衡架构

负载均衡(Load Balancer)是指把用户访问的流量,通过【负载均衡器】,根据某种转发的策略,均匀的分发到后端多台服务器上,后端的服务器就可以独立的响应和处理请求,从而实现分散负载的效果。负载均衡技术提高了系统的服务能力,提升性能,增强了应用的可用性。



  • http重定向负载均衡

根据用户的http请求计算出一个真实的web服务器地址,并将该web服务器地址写入http重定向响应中返回给浏览器,由浏览器重新进行访问。

优点:实现简单

缺点:用户一次请求需要http请求重定向转发,效率低下;服务集群中的服务器地址对外暴漏,安全性低。

  • DNS负载均衡,常用于地域上的流量均衡(就近原则)、

在DNS服务器上配置多个域名对应IP的记录。

优点:直接将负载均衡的工作交给了DNS,为网站管理维护省掉了很多麻烦,不用多次域名解析,访问速度快,有效改善性能。

缺点:服务集群中的服务器地址对外暴漏,安全性低。由于DNS缓存的问题,配置修改生效不及时。

  • 反向代理负载均衡(基于七层代理),如ngnix

反向代理服务器在提供负载均衡功能的同时,管理着一组应用服务器,根据负载均衡算法将请求的浏览器访问转发到不同的应用服务器处理,处理结果经过反向服务器返回给浏览器。

优点:基于软件,部署简单,成本便宜,无需额外采购,可进行技术优化。适合中小分布式系统使用。应用服务器地址不能直接暴露在外,不需要使用外部IP地址。

缺点:负载均衡器需要进行http完整请求与响应报文(分包传输)的构建与封装,性能比较弱,基于7层的负载均衡处理量一般只有几万/秒。负载均衡器,本身有资源的最大限制,有可能成为传输瓶颈;服务伸缩扩展有一定限制。另外,反向代理服务作为沟通桥梁就需要配置双网卡、外部内部两套IP地址。

  • IP负载均衡

在网络层通过修改目标IP地址进行负载均衡。该方式在响应请求时速度较反向服务器负载均衡要快, 但当请求数据较大(大型视频或文件)时,速度反应就会变慢。

优点:该方式在响应请求时速度较反向服务器负载均衡要快;一般能达到几十万/秒的处理量,无需进行http报文的构建与封装,负载均衡器通过修改TCP/IP报文的源IP地址与目的IP地址,实现均衡。基于软件,成本便宜,无需额外采购,可进行技术优化。

缺点:由于所有请求和响应都要经过负载均衡服务器,集群的最大响应数据吞吐量将受到负载均衡服务器网卡带宽的限制,对于提供下载服务或者视频服务等需要大量传输数据的站点而言,这是难以满足需求的。

  • 数据链路层负载均衡

在数据链路层修改Mac地址进行负载均衡,负载均衡服务器的IP和它所管理的web 服务群的虚拟IP一致。它不需要负载均衡服务器进行地址的转换,但是对负载均衡服务器的网卡带宽要求较高。

优点:负载均衡器通过修改通信协议数据包的mac地址进行负载均衡,将请求链路层数据的MAC地址修改为目的服务器,并不修改数据包目的IP,由于服务器集群所有服务器的虚拟IP地址和负载均衡服务器IP地址一致,因此数据可以正常传输到达目标应用服务器上,该服务器处理完之后,将响应数据包发送到网关服务器,网关服务器直接将数据包发送给用户浏览器,响应数据不需要通过负载均衡服务器,这样就避免了负载均衡服务器成为传输瓶颈的可能。这种数据传输方式又称为三角传输。使用三角传输模式的链路层负载均衡是目前大型网站使用最为广泛的一种负载均衡手段。对应用服务的集群伸缩性也更容易。

缺点:对负载均衡服务器的网卡带宽要求高。

  • 基于硬件负载均衡 F5

F5的全称是F5-BIG-IP-GTM,是最流行的硬件负载均衡设备,其并发能力达到百万级。该方式能够实现多链路的负载均衡和冗余,可以接入多条ISP链路,在链路之间实现负载均衡和高可用。

优点:省心省事;性能是非常的好,每秒能处理的请求数达到百万级,即几百万/秒的负载,在负载均衡的算法方面还支持很多灵活的策略,同时还具有一些防火墙等安全功能。可接入多条ISP链路,在链路之间实现负载均衡和高可用。

缺点:价格昂贵。这类设备一般用在大型互联网公司的流量入口最前端,以及政府、国企等不缺钱企业会去使用。一般的中小公司是不舍得用的。




  • 负载均衡算法

1. 轮询:所有请求被依次分发到每个应用服务器上,适合于所有服务器硬件都相同的场 景。

2. 加权轮询:根据应用服务器硬件性能的情况,在轮询的基础上,按照配置的权重将请 求分发到每个服务器,高性能的服务器分配更多请求。

3. 随机:请求被随机分配到各个应用服务器,在许多场合下,这种方案都很简单实用, 因为好的随机数本身就很均衡。如果应用服务器硬件配置不同,也可以很容易的使用 加权随机算法。

4. 少连接:记录每个应用服务器正在处理的连接数(请求数),将新到的请求分发到 少连接的服务器上,应该说,这是符合负载均衡定义的算法。 实现比较困难,容易出错;均衡精确,意义不大。

5. 源地址散列:根据请求来源的IP地址进行Hash计算,得到应用服务器,该算法可以保 证同一个来源的请求总在同一个服务器上处理,实现会话粘滞。




应用服务器集群的session管理(有状态)



  • session复制

缺点:不利于服务伸缩性扩展;session复制有性能损耗。

  • session绑定 share nothing

缺点:各用户session数据分散;互相隔离;单点故障,数据容易丢失。

  • 利用cookie记录session

优点:实现简单,实用,应用服务器不需要存储

缺点:cookie大小有限制;安全性低;特定条件下,浏览器会禁止使用cookie

  • session服务器

优点:session统一管理,数据不容易丢失;应用服务器不需要关心session,有利于应用服务器的伸缩性扩展。



用户头像

Kaven

关注

还未添加个人签名 2019.04.13 加入

还未添加个人简介

评论

发布
暂无评论
极客时间架构师培训 1 期 - 第 5 周总结