秒杀笔记 —— 方案选择

秒杀笔记 —— 方案选择

数据的动静分离

秒杀的场景中,对于系统的要求其实就三个字:快、准、稳。

动静分离设计方向 —— “快”

怎样做到“快”?

  • 提高单次请求效率
  • 减少不必要的请求

何为动静分离

用户请求的数据(如HTML页面)划分为“动态数据”和“静态数据”,“动态数据”和“静态数据”主要区别就是看页面输出的数据是否和URL、浏览者、时间、地域相关,以及是否含有Cookie等私密数据。 例如:

  • 媒体类网站
    某一篇文章内容,无论是A、B、C…N用户访问都是一样的,那么这篇文章即是典型的静态数据,但它是一个动态页面
  • 淘宝首页
    A、B、C…N用户看到的淘宝首页都不一样,因为淘宝会通过系统自动推荐根据用户画像所推算的商品,那么这些商品即是动态数据

所谓“动态”和“静态”,并不是说数据本身是否动静,而是数据中是否含有和访问者相关的个性化数据。

分离动静数据之后,就可以对分离出来的静态数据做缓存,有了缓存之后,静态数据的“访问效率”自然得以提高。

静态数据缓存三个要点
  • 应把静态数据缓存到离用户最近的地方
    把静态数据(相对不变的数据)缓存起来。常见的缓存方式有:用户浏览器里、CDN上、服务端Cache中等,一定要视情况而定,缓存到离用户最近的地方!
  • 静态化改造就是直接缓存HTTP连接
    系统的静态化改造,静态化改造是直接缓存HTTP连接(不仅仅缓存数据),如下图所示:用户直接请求到Web代理服务器的Http Head与Http Body,把HTTP头和体放到Web代理服务器中,用户可直接获取最近的信息。如Nginx缓存页面。
    在这里插入图片描述
  • 谁来缓存静态数据
    不同语言写的Cache软件处理缓存数据效率各不同,例如Java(不擅长处理大量请求,消耗内存较多,Servlet容器解析HTTP协议慢),所以,可以不在Java层做缓存,而是直接在Web服务器层上做,以此规避语言的天生缺陷,WEB服务器(如Nginx、Apache、Varnish)更擅长处理大并发的静态文件请求。

示例:
通过Nginx配置静态文件加载(待补充)

如何做静态分离改造

分离动态内容的五方面
  • URL唯一化
    比如商品详情页,我们的地址为http://www.xxxx.com/product.htm/id=?,在缓存整个HTTP连接时,URL就可以作为Key(即http://www.xxxx.com/product.htm),然后以id=?来区分
    示例:
    Nginx URL唯一化配置(待补充)
  • 分离浏览者相关的因素
    浏览者相关因素包括是否登陆,以及登陆身份等,这些相关因素可以单独拆分,通过动态请求获取。
  • 分离时间因素
    服务端输出的时间也通过动态请求获取。
  • 异步化地域因素
    详情页面关于地域的信息(例如商品详情中,定位用户位置,或者用户常用位置获取)通过异步的方式获取,也可以通过动态请求方式获取,推荐使用异步方式获取。
  • 去掉Cookie
    服务端输出页面包含Cookie通过代码软件删除,如Web服务器Varnish可以通过 unset req.http.cookie命令去掉Cookie。注意:这里指的去掉Cookie并不是用户端页面不含Cookie,而是在缓存的静态数据中不含有Cookie。

分离出动态内容后,如何组织使用内容页变得尤为重要。其中很多动态内容都会被页面中的其他模块用到,如判断该用户是否已登陆、用户ID是否匹配等,这个时候我们应该将这些信息JSON化(用JSON格式组织这些数据),以便前端使用。

介绍了用缓存方式来处理静态数据。处理动态内容的方式推荐以下两种:

  • ESI方案(或者SSI)
    Web代理服务器上做动态内容请求,并将请求插入到静态页面中,用户获取的即是组装之后的完整页面。此方式对服务端性能有影响,但是用户体验较好。
  • CSI方案
    单独发起一个JavaScript请求,以便向服务端获取动态内容。这种方式服务端性能更佳,可用户端页面可能会出现延时(等待),体验较差。

动态分离的几种架构方案

即是对用户对请求路径进行合理架构。根据架构复杂度,分为3种架构可选:实体机单机布署,统一Cache层,上CDN;

实体机单机布署

将虚拟机替换为实体机,增大Cache容量,并采用一致性Hash分组方式提升命中率。将Cache分组对目的是为了提供命中率及访问热点对平衡。Hash分组越少,缓存命中率越高,短板是单个商品集中一个分组时,容易导致Cache被击穿,通过适当增加多个相同分组,平衡访问热点和命中率的问题。
实体机单机布署方案结构图 (Nginx + Cache + Java) :
在这里插入图片描述

扫描二维码关注公众号,回复: 5360726 查看本文章
  • 实体机单机布署优点:
  1. 没有网络瓶颈,而且可以使用大内存;
  2. 既能提升命中率,又能减少Gzip压缩;
  3. 减少Cache失效压力,因为采用定时失效方式,例如只缓存3秒,过期即自动失效;

这个方案中,将虚拟机或者容器运行的Java应用换成实体机,优点是增加单机的内存容量,缺点则是在一定程度下会造成CPU的浪费,因为单个JAVA进程很难用完整个实体机的CPU。

另外,一个实体机上布署来Java应用有作为Cache来使用,运维成本难度会提高,所以这个方案属于一个这种方案,当公司内部只有一个秒杀业务时,我们可以选择这样布署,但是,如果涉及多个类似业务,我们应该把Cache和应用单独分离,把Cahce层抽离公用比较合理,即下面要介绍的统一Cache层

统一Cache层

将单机的Cache统一分离出来,形成一个单独的Cache集群 (推荐) 。 该方案结构图如下所示:
在这里插入图片描述
Cache统一,降低运维成本,并且方便接入其它动态化系统。此外,它的其他优点:

优点 描述
独立Cache层 Cache层公用,Java应用值关系本身业务,调用公用Cache即可。
易于维护 统一管理,配合监控、自动化配置等功能让独立Cache层可以高效工作。
内存共享 最大化利用内存,多系统之间内存可以动态切换,从而能够有效应对各种攻击。

此方案降低了维护成本(运维和集群设计),可依然有自己的缺点:

缺点
Cache 层内部交换网络成为瓶颈
缓存服务器网卡也会是瓶颈
机器少风险大,挂掉一台就会影响很大一部分缓存数据

要解决上面的问题,可在对Cache做Hash分组,即一组Cache缓存的内容相同,这样能够避免热点数据过度集中导致新的瓶颈产生。

上CDN

动静分离是离用户越近,效果会越好,将Cache放到离用户更近的CDN上,是进一步的优化方案,做到这点需要先解决以下的问题:

  • 失效问题
    缓存在CDN上的时效要可控到秒级,以便让分布在全国各地的Cache同时失效,对CDN的失效系统要求较高
    示例:
    如何做到CDN Cache失效?

  • 命中率问题
    Cache最重要的一个衡量指标就是“高命中率”,不然Cache的存在就失去了意义。同样,如果将数据全部放到全国到CDN上,必然导致Cache分散,而Cache分散又会导致访问请求命中同一个Cache的可能性降低,固然命中率就会成为问题。

  • 发布更新问题
    业务模块迭代更新较快,发布系统就要变得简洁高效,并且要考虑有问题时,如何混滚和排查问题。

从上面的分析看,将商品详情系统放到全国的CDN节点并不现实,因为存在失效问题、命中率问题以及系统发布更新问题,那是否可以选择若干个节点尝试实施呢?“可以”,但是节点需要满足以下5个因素:

因素
靠近访问量比较集中的地址;
离主站相对较远;
节点到主站间网络比较好,而且稳定;
节点容量比较大,不会占用其他CDN太多资源;
节点不能太多

基于上面的这些因素,选择CDN的二级Cache 比较合适,因为 二级Cache数量偏少,容量更大,用户请求先回源(什么叫CDN回源)到CDN的二级Cache中,如果没命中再回源站获取数据,布署方式如下图所示:
在这里插入图片描述
使用CDN的二级Cache作为缓存,可达到与当前服务端静态化Cache类似的命中率,因为节点数不多,Cache不是分散的,访问量也比较集中,这样就解决来命中率问题。
除此之外,CDN化还有以下几个特点:

  • 1.把整个页面缓存在用户浏览器中;
  • 2.如果强制刷新整个页面,也会请求CDN;
  • 3.实际有效请求,只有用户点击“刷新抢宝”按钮的点击;

这样将90%的静态数据缓存在用户端或CDN上,秒杀启动时,用户实际只需要点击特殊的“刷新抢宝”按钮,而不需要刷新整个页面。

猜你喜欢

转载自blog.csdn.net/Cy_LightBule/article/details/87941634