高并发设计

高并发设计

前言

个人关于高并发的一些心得体会,不定期持续更新中,如果错误欢迎指正。

1.多级缓存的策略

  • 目的:减少客户端和服务端之间的交互,防止大量的客户端请求穿透到服务端甚至到数据库,我们将资源放置在离客户更近的位置,使得用户可以更快的收到应答。
缓存可以分为两大类:
1.客户端缓存
2.服务端缓存

请求也可以分为两大类:
1.静态资源的访问
2.动态接口的访问

1.1 客户端缓存策略

如果系统是B/S架构,我们可以利用localstorage和sessionstorage的功能来缓存一些数据,从而来减少客户端与服务端的交互,例如:用户的基本信息(加密存储),静态的系统参数,静态的字典资源等,配合使用失效时间的设置来达到缓存的更新。

如果是c/s架构或者app应用,我们可以利用本地机器设备的内存和数据库来存储更大的资源,比如页面,样式,图片,音频视频等资源,也可以存储业务数据,配置和系统字典资源,并配合定期的过期策略,就可以达到缓存更新的目的,从而减少客户端与服务端交互的次数。

同时我们需要充分利用http协议的缓存功能来缓存我们的页面资源,css样式,js脚本,图片资源等,同时设置缓存策略和过期时间保证资源的更新。

1.2 CDN

CDN的全称是Content Delivery Network,即内容分发网络。CDN是构建在现有网络基础之上的智能虚拟网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。CDN的关键技术主要有内容存储和分发技术。

正常情况下我们希望资源离用户更近,cdn就是用来解决这个问题。
在这里插入图片描述
如上图,假设现在有一个短视频文件,在北京的用户打开就比较快,上海相对慢一点,深圳的用户打开更慢,这是因为距离产生的网络延迟和网络冲突引起的。解决的办法呢也很简单,我们只需要在用户周边部署服务节点,让我们的资源离用户更近,这种边缘化的存储也被称作为边缘存储或者边缘服务。如下图

在这里插入图片描述
cdn我们主要用来存储各种静态文件比如html,js,css,音视频等,他可以有效地缓解我们服务器地压力,降低带宽冲击,极大地提升用户体验,同时cdn这种多节点的模式代表着绝大多数公司没有部署的实力,因为需要在全国各地架设大量的网络节点,所以一般会借助网络运营商或者云服务运营商等。

cdn的管理节点众多,资源同步分发就需要一个管理节点,这个节点负责资源的上传,管理,分发。

资源加载模式

cnd的资源加载模式分为两种模式,一种是推模式,一种是拉模式。

推模式

推模式主要是由管理节点主动把资源推向各个边缘服务器,这个在程序发布和升级的时候需要注意我们很多的时候需要刷新cdn,由于部署节点在全国各地,各个地方的节点更新时间也是不一定的,所以当我们一次发布的时候,往往需要等几分钟甚至几十分钟才能完成全国节点的一个刷新动作

拉模式

拉模式可以设置我们的资源有效期,用户在访问边缘服务节点的时候发现资源过期了回到管理节点拉取资源,他的机制和我们的应用的其他缓存机制是一样的。

cdn是一个典型的空间换时间的概念。

1.2.1 cdn案例:

结合阿里淘系2020年双11的淘宝实践和淘宝鹿班团队的技术分享,在图片业务里,如何使用CDN以及如何解决挑战和困难。
(转载:阿里云官方解释cdn阿里官方团队技术讲解
通过以下案例,您可以了解CDN的工作原理。

假设您的加速域名为www.a.com,接入CDN网络,开始使用加速服务后,当终端用户(北京)发起HTTP请求时,处理流程如下图所示。
在这里插入图片描述

工作原理
当终端用户(北京)向www.a.com下的指定资源发起请求时,首先向LDNS(本地DNS)发起域名解析请求。
LDNS检查缓存中是否有www.a.com的IP地址记录。如果有,则直接返回给终端用户;如果没有,则向授权DNS查询。
当授权DNS解析www.a.com时,返回域名CNAME www.a.tbcdn.com对应IP地址。
域名解析请求发送至阿里云DNS调度系统,并为请求分配最佳节点IP地址。
LDNS获取DNS返回的解析IP地址。
用户获取解析IP地址。
用户向获取的IP地址发起对该资源的访问请求。
如果该IP地址对应的节点已缓存该资源,则会将数据直接返回给用户,例如,图中步骤7和8,请求结束。
如果该IP地址对应的节点未缓存该资源,则节点向源站发起对该资源的请求。获取资源后,结合用户自定义配置的缓存策略,将资源缓存至节点,例如,图中的北京节点,并返回给用户,请求结束。配置缓存策略的操作方法,请参见缓存配置。
由上述案例可知、
(1)CDN的加速资源是跟域名绑定的。
(2)通过域名访问资源,首先是通过DNS分查找离用户最近的CDN节点(边缘服务器)的IP
(3)通过IP访问实际资源时,如果CDN上并没有缓存资源,则会到源站请求资源,并缓存到CDN节点上,这样,用户下一次访问时,该CDN节点就会有对应资源的缓存了。

在阿里双十一的背景下,商品的主图贯穿整个导购和交易链路,相比文字,图片更能吸引眼球,主图对消费者的购物决策有很大的影响。主图上表达的内容各式各样,但其中一定少不了的一定是价格的表达,长期以来,主图上的价格表达都是商家自己维护,商品价格发生变化后,手动去换图。这样做,会带来3个问题:
(1)价格的准确性:商家手动填写的图片价格,跟实际的购买价可能不一致,造成不好的用户体验。 (2)价格更新的及时性:有时候,由于优惠券/品类券的生效失效,会导致商品的价格变化会很频繁,商家根本来不及换图。
(3)商家的操作成本:手动修改图片的价格,成本还是很高的,需要通过ps等软件修改图片,重新上传,编辑商品。

淘宝网有上亿的商品,光大促商品就有几千万,因此,价格变化导致的图片变化频率非常高。最高的就是在双11的0点,全部大促商品的价格都会由日常价格变成大促价格。这就意味着,大促高峰期,有上千万的图片刚生成就会被用户访问。因而会带来极大的带宽冲击。

淘宝图片空间和CDN的架构

淘宝整个图片的访问链路有三级缓存(客户端本地、CDN L1、CDN L2),所有图片都持久化的存储到OSS中。真正处理图片的是img-picasso系统,它的功能比较复杂,包括从OSS读取文件,对图片尺寸进行缩放,编解码,所以机器成本比较高。

CDN的缓存分成2级,合理的分配L1和L2的比例,一方面,可以通过一致性hash的手段,在同等资源的情况下,缓存更多内容,提升整体缓存命中率;另一方面,可以平衡计算和IO,充分利用不同配置的机器的能力。
在这里插入图片描述

用户访问图片的过程如下:
(1)用户通过手机淘宝来搜索商品或者查看宝贝详情。
(2)详情/搜索/推荐通过调用商品中心返回商品的图片URL。
(3)客户端本地如果有该图片的缓存,则直接渲染图片,否则执行下一步。
(4)从CDN L1回源图片,如果L1有该图片的缓存,则客户端渲染图片,同时缓存到本地,如果L1没有缓存,则执行下一步。
(5)从CDN L2回源图片,如果L2有该图片的缓存,则客户端渲染图片,同时CDN L1及客户端缓存图片内容,如果CDN L2没有缓存该图片,则执行下一步。
(6)从图片空间回源图片,图片空间会从OSS拉取图片源文件,按要求进行尺寸缩放,然后执行编解码,返回客户端能够支持的图片内容,之后客户端就可以渲染图片,同时CDN的L1、L2以及客户端都会缓存图片内容。

频繁换图带来的技术挑战

在这里插入图片描述

当商品的价格发生变化时,淘宝团队会使用新的价格重新合成图片,更新商品中心中存储的图片URL。这样会带来2个问题:
(1)CDN及手机淘宝原本缓存的图片内容失效了,用户访问图片会全部回源到img-picasso。
(2)由于更改了商品的字段,交易的核心应用(购物车和商品中心)的缓存也失效了,用户浏览及购物时,对商品的访问会走到db。源站img-picasso处理图片,以及查询商品DB,都是非常消耗资源的。CDN及商品的缓存命中率降低后,对源站img-picsasso以及db会产生巨大的压力。拿CDN缓存为例,简单计算一下,CDN平时的命中率是98%,假设命中率降低1个点,对源站的压力就会增加1/3(原本承担2%的流量,现在需要承担3%的流量),意味着img-picasso需要扩容1/3。如果全网一半的图片都同时变化,cdn的命中率降到50%,对img-picasso的访问量就会增加25倍,这个扩容成本肯定没法接受。

解决这2个问题,对应的有2个办法:
(1)改图保持图片URL不变,可以避免商品链路的缓存失效。
(2)在访问高峰到来之前,提前预热图片到CDN,可以避免CDN缓存失效对源站的压力。

下面,介绍下具体是怎么做到这2点的。频繁换图的应对方案改图保持图片URL不变

频繁换图的应对方案
改图保持图片URL不变

在这里插入图片描述
图片内容发生变化时,执行下面2个操作:
(1)更新OSS内容:使用新的图片内容替换OSS中老的图片内容
(2)刷新CDN缓存:清除CDN之前缓存的图片内容

这样,用户再次访问图片时,发现CDN没有缓存,就会回源到img-picasso,从OSS拉取新的图片内容

由于图片URL没有变化,就不必去更新商品中心的图片链接,这样商品链路的缓存可以保持不变。
在真正实施这个方案的过程中,淘宝团队遇到了几个问题,简单跟大家分享下:

OSS三地同步

淘宝的图片空间,承载了淘系所有图片的上下行稳定性保障,为了保障高可用,一份资源会存储到三地OSS。图片上传时,默认只上传一地,利用OSS的能力,自动同步到另外两地。

但是使用URL不变方案,CDN缓存已经清除完成后,如果另外2地的OSS还未同步完成,用户访问后,就会回源到旧的图片内容,发现图片内容没有变化。

针对该问题,淘宝团队将异步同步OSS软链的模式,改成三地同步建软链,三地都返回成功后,再去清除CDN缓存,这就保证了用户访问的图片一定是最新的内容。

在这里插入图片描述

图片尺寸收敛

同一张商品图片会用于不同的场景坑位展现,不同的坑位对图片的尺寸有不同的要求。为此,图片空间提供了一项功能,可以方便的生成不同尺寸的缩率图。只需要访问图片时,给图片增加不同的后缀,img-picasso源站就可以按要求进行图片进行缩放。

由于历史原因,之前对缩放的尺寸种类没有限制,导致CDN上的图片后缀格式多达2400种+,TOP6格式覆盖率46%,TOP15格式覆盖率64%。这意味着,一张图片,在cdn上最多可能有2400+个不同的url,当图片内容变化后,要把这些缓存全部清掉,才能保证所有用户看到的图片都是新内容。

为了解决这个问题,淘宝团队对域名格式进行了收敛。

图片空间对于图片质量压缩参数的规则如下:

  • 图片质量参数常见有一下8种形式:Q90、Q75、Q50、Q30、q90、q75、q50、q30
  • 图片锐化参数常见有一下3种形式:s100,s150,s200

他们重新将图片质量定义为高质量图片和低质量图片,收敛格式为 q90 和 p50s150
这样,就可以把2000多种格式收敛到6种主要格式,CDN清除缓存才变得可行。

多副本清除CDN缓存

通过图片尺寸收敛,每张图片只需要清除6个不同的url就可以了,那能不能进一步提升刷新效率呢?

为此,阿里云CDN提供了多副本刷新的解决方案:每种不同后缀的图片,作为图片的一个副本,在CDN的swift层增加一层KV结构,存储url和不同副本的映射关系,清除缓存时,可以通过该结构找到所有副本,实现快速清除所有副本。这样,每张图片,我们只需要调用一次CDN清除缓存接口就可以了,极大提升了CDN缓存刷新效率。

在这里插入图片描述

图片域名收敛

淘系的图片域名有300多种,主要有下面2个原因:
(1)图片完整的链接太长,所以存储时经常只存最后一段,业务自己来拼域名,很多业务就自己申请了一个图片域名来拼。
(2)PC时代,浏览器对同一域名下的并发请求数是有限制的,不同浏览器不一样,一般6个左右。

为了突破该限制,一些业务就会申请多个域名,随机的拼不同的域名。

前面我们讲过,CDN的缓存是跟域名绑定的,不管是缓存命中还是缓存清除,都只能针对一个域名。

显然不可能改一张图,就去对300个域名调用CDN刷新。于是我们考虑对图片域名进行收敛,使得用户对图片的访问都路由到同一个域名,淘宝团队希望将所有的图片访问统一收敛到http://picasso.alicdn.com,具体实现方式如下:

1)对于手淘和猫客客户端,图片访问都收口在图片库,推进图片库进行改造,符合一定规则的url,统一收敛到http://picasso.alicdn.com,实现了域名的一刀切。
(2)对于PC浏览器端,就比较麻烦了,没有统一收口的地方。只能退而求其次,针对访问最多的6大域名,在cdn上配置域名转发规则,重定向到picasso域名。

在这里插入图片描述
通过这种方式,实现了全网99%以上的图片访问流量都路由到picasso域名,图片内容发生变化时,通过清除picasso域名的cdn缓存,就能保证基本所有的场景都能看到新的图片内容。

客户端及浏览器缓存

通过多副本和图片域名收敛,cdn的缓存问题得到了解决。但在cdn之上,用户图片访问首先是来自客户端或者浏览器,这里也会有一层缓存。

大家知道,浏览器的缓存都遵循标准的http max-age协议,指定该header后,到了时间图片就会失效,访问到新的图片。所以我们可以在源站img-picasso回源给cdn时,添加max-age协议头,值为1分钟,cdn会原封不动的透给浏览器,这样浏览器就可以实现1分钟内图片缓存失效,重新到cdn拉新的图片资源

对于手机淘宝客户端,我们在原有的LRU缓存机制之上,另外支持标准的http协议。这样,手机淘宝也实现了1分钟内图片缓存失效。

提前预热CDN图片

通过改图保持图片URL不变,我们解决了改图对商品链路缓存的影响。但是,图片变化时,虽然URL没有变,但我们清除了CDN缓存,导致用户访问时还是会回源到img-picasso源站,所以对图片源站的压力依然存在。

在这里插入图片描述
商品的价格变化大部分发生在大促节奏变化的时刻,基于这个特点,我们通过提前合成图片,提前预热到CDN,可以实现图片切换瞬间生效,同时对源站没有压力。

具体方案如下:
(1)提前合成多波段图片:我们知道大促期间商家集中换图的时间点后,按这些时间点把图片的展示分成多个波段,每个波段图片提前合成,并提前将图片URL写入到商品中心扩展结构中。
(2)图片访问路由:营销系统根据配置的大促氛围切换计划,告诉鹿班图片二方包,当前是哪个波段,鹿班根据当前波段及场景,返回正确的图片URL给各个场景。
(3)图片渲染:各个场景拿到图片URL后,结合自身的业务逻辑,决定是否要展现该图片。
(4)CDN图片预热:为了避免图片集中切换时,把源站击垮,会在集中切换前把这些冷图片内容预热到CDN。
(5)波段内图片变化:提前合成各个波段图片后,商家可能会临时发券/改价,导致商品价格再次变化,对于这类换图需求,为了避免更新商品中心的图片URL,通过刷CDN缓存的方式实现。

1.3 负载缓存

我们一般采用负载均衡来做集群部署,来降低单一节点的压力,增强系统的可靠性,负载的设备可以是硬件F5,可以是软件lvs,nginx,haproxy。其中F5和lvs是四层负载,haproxy是四层和七层负载,nginx只能做七层负载。
在这里插入图片描述

如果我们想在负载设备上增加缓存,我们需要做七层负载,也就是我们的应用层,最常见的工具就是nginx,首先我们需要用nginx做动静分离,将我们的html,js,css等静态资源部署到nginx服务器上或者指定的静态资源服务器通过反向代理代理服务器(优先跟nginx统一服务器,减少网络带宽传输导致的性能问题),后端服务部署到其他服务器上并通过反向代理代理。

NGINX

在nginx上可以对静态文件设置协商缓存,固定失效时间的缓存和不缓存, 开启缓存后前端在请求静态页面的时候会通过我们的内存磁盘依次查找,如果找到了立即返回,这个响应时间几乎为0,如果请求到nginx服务器并且缓存名字返回状态码304,nginx将不会去加载文件,而是直接从缓存里面返回。

nginx也可以对我们的后端接口进行动态代理,比如我们查询一个订单,如果我们将这个订单的请求进行缓存,当缓存命中的时候将不会把请求转发给服务器,直接把应答报文返回给前端,但是这种方式是不推荐使用的,我们一般只用nginx做静态资源缓存。

同时我们可以在nginx上开启gzip压缩,来提升我们的网络传输效率,经过个人测试打开一个页面加载2m的东西需要1.2秒,而开启nginx和缓存只需要191毫秒,对我们的性能提升是巨大的.

案例:(最近没空,有空再补)

1.4 应用缓存

应用缓存就是我们后端服务的内存

**未完待续~~~~~~~~~~~~~~~~~~~~~~**

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值