淘宝的图片访问,有98%的流量都走了CDN缓存,只有2%会回源到源站,节省了大量的服务器资源。swift
可是,若是在用户访问高峰期,图片内容大批量发生变化,大量用户的访问就会穿透cdn,对源站形成巨大的压力。浏览器
今年双11,淘宝鹿班的主图价格表达升级项目,就面临了这种挑战,让咱们看看是如何解决的吧。缓存
内容分发网络(Content Delivery Network,简称CDN)是创建并覆盖在承载网之上,由分布在不一样区域的边缘节点服务器群组成的分布式网络。sass
CDN应用普遍,支持多种行业、多种场景内容加速,例如:图片小文件、大文件下载、视音频点播、直播流媒体、全站加速、安全加速。安全
借用阿里云官网的例子,来简单介绍CDN的工做原理。服务器
假设经过CDN加速的域名为www.a.com
,接入CDN网络,开始使用加速服务后,当终端用户(北京)发起HTTP请求时,处理流程以下:网络
www.a.com
下的指定资源发起请求时,首先向LDNS(本地DNS)发起域名解析请求。www.a.com
的IP地址记录。若是有,则直接返回给终端用户;若是没有,则向受权DNS查询。www.a.com
时,返回域名CNAME www.a.tbcdn.com
对应IP地址。从这个例子能够了解到:架构
(1)CDN的加速资源是跟域名绑定的。并发
(2)经过域名访问资源,首先是经过DNS分查找离用户最近的CDN节点(边缘服务器)的IP异步
(3)经过IP访问实际资源时,若是CDN上并无缓存资源,则会到源站请求资源,并缓存到CDN节点上,这样,用户下一次访问时,该CDN节点就会有对应资源的缓存了。
商品的主图贯穿整个导购和交易链路,相比文字,图片更能吸引眼球,主图对消费者的购物决策有很大的影响。主图上表达的内容各式各样,但其中必定少不了的必定是价格的表达。
长期以来,主图上的价格表达都是商家本身维护,商品价格发生变化后,手动去换图。这样作,会带来3个问题:
(1)价格的准确性:商家手动填写的图片价格,跟实际的购买价可能不一致,形成很差的用户体验。
(2)价格更新的及时性:有时候,因为优惠券/品类券的生效失效,会致使商品的价格变化会很频繁,商家根原本不及换图。
(3)商家的操做成本:手动修改图片的价格,成本仍是很高的,须要经过ps等软件修改图片,从新上传,编辑商品。
今年双11,咱们淘宝鹿班团队,试图经过技术手段来解决这些问题。当商品价格发生变化后,系统自动计算新的价格,自动合成图片,而后更新商品主图。
咱们知道,淘宝网有上亿的商品,光大促商品就有几千万,所以,价格变化致使的图片变化频率很是高。最高的就是在双11的0点,所有大促商品的价格都会由平常价格变成大促价格。
这就意味着,大促高峰期,有上千万的图片刚生成就会被用户访问。那这个状况会产生什么问题呢,让咱们先了解下淘宝的图片空间和CDN的架构,就清楚了。
四、淘宝图片空间和CDN的架构
================
淘宝整个图片的访问链路有三级缓存(客户端本地、CDN L一、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的L一、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点的。
图片内容发生变化时,执行下面2个操做:
(1)更新OSS内容:使用新的图片内容替换OSS中老的图片内容
(2)刷新CDN缓存:清除CDN以前缓存的图片内容
这样,用户再次访问图片时,发现CDN没有缓存,就会回源到img-picasso,从OSS拉取新的图片内容。
因为图片URL没有变化,就没必要去更新商品中心的图片连接,这样商品链路的缓存能够保持不变。
在真正实施这个方案的过程当中,遇到了几个问题,简单跟你们分享下:
淘宝的图片空间,承载了淘系全部图片的上下行稳定性保障,为了保障高可用,一份资源会存储到三地OSS。图片上传时,默认只上传一地,利用OSS的能力,自动同步到另外两地。
可是使用URL不变方案,CDN缓存已经清除完成后,若是另外2地的OSS还未同步完成,用户访问后,就会回源到旧的图片内容,发现图片内容没有变化。
针对该问题,咱们将异步同步OSS软链的模式,改为三地同步建软链,三地都返回成功后,再去清除CDN缓存,这就保证了用户访问的图片必定是最新的内容。
同一张商品图片会用于不一样的场景坑位展示,不一样的坑位对图片的尺寸有不一样的要求。为此,图片空间提供了一项功能,能够方便的生成不一样尺寸的缩率图。只须要访问图片时,给图片增长不一样的后缀,img-picasso源站就能够按要求进行图片进行缩放。
因为历史缘由,以前对缩放的尺寸种类没有限制,致使CDN上的图片后缀格式多达2400种+,TOP6格式覆盖率46%,TOP15格式覆盖率64%。这意味着,一张图片,在cdn上最多可能有2400+个不一样的url,当图片内容变化后,要把这些缓存所有清掉,才能保证全部用户看到的图片都是新内容。
为了解决这个问题,咱们对域名格式进行了收敛。
图片空间对于图片质量压缩参数的规则以下:
咱们从新将图片质量定义为高质量图片和低质量图片,收敛格式为 q90 和 p50s150
这样,就能够把2000多种格式收敛到6种主要格式,CDN清除缓存才变得可行。
经过图片尺寸收敛,每张图片只须要清除6个不一样的url就能够了,那能不能进一步提高刷新效率呢?
为此,阿里云CDN为咱们提供了多副本刷新的解决方案:每种不一样后缀的图片,做为图片的一个副本,在CDN的swift层增长一层KV结构,存储url和不一样副本的映射关系,清除缓存时,能够经过该结构找到全部副本,实现快速清除全部副本。这样,每张图片,咱们只须要调用一次CDN清除缓存接口就能够了,极大提高了CDN缓存刷新效率。
淘系的图片域名有300多种,主要有下面2个缘由:
(1)图片完整的连接太长,因此存储时常常只存最后一段,业务本身来拼域名,不少业务就本身申请了一个图片域名来拼。
(2)PC时代,浏览器对同一域名下的并发请求数是有限制的,不一样浏览器不同,通常6个左右。为了突破该限制,一些业务就会申请多个域名,随机的拼不一样的域名。
前面咱们讲过,CDN的缓存是跟域名绑定的,无论是缓存命中仍是缓存清除,都只能针对一个域名。
咱们显然不可能改一张图,就去对300个域名调用CDN刷新。因而咱们考虑对图片域名进行收敛,使得用户对图片的访问都路由到同一个域名,咱们但愿将全部的图片访问统一收敛到picasso.alicdn.com,具体实现方式以下:
(1)对于手淘和猫客客户端,图片访问都收口在图片库,咱们推动图片库进行改造,符合必定规则的url,统一收敛到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分钟内图片缓存失效。
经过改图保持图片URL不变,咱们解决了改图对商品链路缓存的影响。可是,图片变化时,虽然URL没有变,但咱们清除了CDN缓存,致使用户访问时仍是会回源到img-picasso源站,因此对图片源站的压力依然存在。
咱们发现,商品的价格变化大部分发生在大促节奏变化的时刻,基于这个特色,咱们经过提早合成图片,提早预热到CDN,能够实现图片切换瞬间生效,同时对源站没有压力。具体方案以下:
(1)提早合成多波段图片:咱们知道大促期间商家集中换图的时间点后,按这些时间点把图片的展现分红多个波段,每一个波段图片提早合成,并提早将图片URL写入到商品中心扩展结构中。
(2)图片访问路由:营销系统根据配置的大促氛围切换计划,告诉鹿班图片二方包,当前是哪一个波段,鹿班根据当前波段及场景,返回正确的图片URL给各个场景。
(3)图片渲染:各个场景拿到图片URL后,结合自身的业务逻辑,决定是否要展示该图片。
(4)CDN图片预热:为了不图片集中切换时,把源站击垮,咱们会在集中切换前把这些冷图片内容预热到CDN。
(5)波段内图片变化:提早合成各个波段图片后,商家可能会临时发券/改价,致使商品价格再次变化,对于这类换图需求,为了不更新商品中心的图片URL,咱们经过本文上一章节刷CDN缓存的方式实现。
CDN技术普遍应用于互联网的各个场景,现在的CDN服务商,都提供了很是简单的业务接入方式,并且CDN的费用每一年都在下降,这一切使得CDN的接入和使用成本愈来愈低。
本文经过淘宝图片业务的例子,为你们阐述了使用CDN过程当中可能遇到的问题和解决思路。
淘宝的图片业务除了访问量大,还会面临更新频繁的问题。图片的频繁更新,一方面会因为商品上的图片url变化,致使商品缓存失效,另外一方面会大幅下降CDN的图片访问缓存命中率。
针对图片url变化致使商品缓存失效的问题,咱们经过刷新cdn缓存,用户访问时从新回源的方式,实现了改图保持图片url不变,这个过程当中了,咱们解决了一些列的问题,包括:OSS三地同步更新、图片尺寸收敛、图片域名收敛、客户端及浏览器本地缓存。
针对改图下降CDN图片缓存命中率的问题,咱们根据业务的特色,提早合成不一样波段的图片,并预热到CDN,保障了源站的安全。
目前,淘宝上用户看到的图片,都是提早合成好的。将来,咱们考虑在用户访问图片时,实时合成图片。经过这项技术,能够实时感知业务更多的实时信息,能够根据这些信息,在图片上合成当前用户或者环境更匹配的文案/元素等内容,给用户带来更多的惊喜。
固然,实时合图也会面临更多的挑战,如:计算能力、合图性能。此外,对于CDN而言,因为每次用户访问的内容是临时合成的,CDN的缓存策略也是一个很大的挑战。
技术来驱动业务!!!淘宝鹿班团队,长期聚焦在图片及视频领域,经过技术创新,提高商家的经营效率及用户的体验,若是你对图片或者视频技术感兴趣,或者但愿接触到高并发的工程系统,但愿经过code改变世界,欢迎加入咱们!!! zhaoming.ywt@taobao.com
(更多干货请关注【淘系技术】公众号)(更多干货请关注【淘系技术】公众号)(更多干货请关注【淘系技术】公众号)