淘宝秒杀是什么意思啊(聊聊什么是秒杀系统(上))

你好,我是利奥。

前段时间介绍了MySQL和Redis的相关技术。大概告一段落,只能说对这两个技术调音原理有了初步的了解,等整个technology stack学的差不多了再回来做第二版的修改。

前言

任何技术的总结都有商业背景。简单的介绍会帮助你更好的理解,顺便输出自己的学习思路。

已经满足了之前一个跨境电商项目的基本需求。如购买需求、积分、会员、购物车、用户、广告、消息通知等。

我们开始考虑特价、秒杀、限时、推荐的一些功能吧。让我无缘无故写,从0到1,肯定不会。一点一点去研究淘宝10年前的技术发展过程当然不会划算。问题是,如何开发设计一个秒杀系统?



有这个想法的时候,我也是疯了。要点如下

  • 老板没有要求。我自己的事太忙了,不得不为自己的私活写一个函数。
  • 开发一个道钉,至少要了解淘宝的开发流程,以及道钉的设计思路。
  • 硬件设施落地实施
  • 原有架构的数据存储模式改变
  • 我仍然没有钱来支持我的想法。毕竟花点时间写代码还是可以的。所以,综上所述,购买秒杀相关的课程,学习前人的思路,再考虑自己的系统规模进行开发是我接下来的任务

    学习思想

    说起学习,相信很多人都会处于以下状态。



    现在信息化太爆炸,很多app和系统很容易被他按照个人喜好影响。我一直觉得应该鞭策自己,给自己一些动力。做时间的主人,做生活的主人。

    至于学习的顺序,建议一点一点学习适合自己能力的技术。很多人基础还没学会,天天嚷嚷着要学微服务、分发、并发。然后在群里,我问他为什么,他说要拿阿里20K。

    20K没那么容易。技术没有捷径。循序渐进才是王道。C#转Java快半年了,刚学微服务。我学微服是因为我领导在会上说我以后可能要学微服。不然吃饱了就没事干了。我要端上这块大骨头。




    秒杀系统的5个原则

    关闭!回到正题!

    数据尽量要少

    数据要尽量少主要有两点:用户请求中附加的数据要尽量少服务器返回给客户端的数据要尽量少千万不要传输无关的字段。

    因为数据在网络上传输是需要时间的,其次,无论是请求数据还是返回数据,都需要服务器做处理,在网络上写的时候服务器通常要做压缩和字符编码,这些都是非常消耗CPU的,所以减少传输的数据量可以显著减少CPU的使用。

    第二层意思是完成一些业务。我们从数据库中读取校验值和保存的数据,这涉及到与数据库的交互。调用其他服务会涉及数据序列化和反序列化,这也是CPU的一大杀手,也会增加延迟。而且数据库本身很容易成为瓶颈,所以越少和数据库打交道越好,数据越简单越小越好。

    这里有一些例子。比如下单的时候,需要根据成交量做出选择,是要用前端到后端的对应值进行实体类拼接,还是前端只传输ID。根据用户ID找到用户的等级,然后根据等级找到这个用户对应的商品价格?



    还有下面的积分ID,是前端传输,还是只是用户ID,查一下积分ID?

    是否有必要将用户的信息保存到缓存中,直接进行Redis incr、decr或反向检查?如果给了缓存,如何保证一致性?(请参考我之前Redis的第七篇文章)



    以上只是一些想法,并不是最好的解决方案。代码还没有优化,只是开发的一个阶段。

    请求数尽量要少

    看的时候第一时间没有回应要求。这里我就以图文并茂的形式介绍一下。



    用户请求的页面返回后,浏览器会用其他额外的请求来渲染这个页面,例如,这个页面所依赖的CSS/JavaScript、图片、Ajax请求都被定义为“额外请求”,这些额外请求要尽量少。因为浏览器发出的每个请求都会有一些消耗,比如建立连接需要三次握手,有时候会有页面依赖或者连接限制,有些请求(比如JavaScript)需要串行加载等等。

    如果不同请求的域名不一样,还涉及到这些域名的DNS解析,可能需要更长的时间。所以我们要记住,减少请求的数量可以显著减少这些因素造成的资源消耗。

    路径尽量要短

    这里的路径主要是关于节点的数量。这些节点可以表示为一个系统或一个新的套接字连接(例如,代理服务器只是创建一个新的套接字连接来转发请求)。在每个节点之后,通常会生成一个新的套接字连接。缩短请求路径不仅可以增加可用性,还可以有效提高性能(减少中间节点的数量可以减少数据的序列化和反序列化),减少延迟(可以减少网络传输时间)。



    依赖尽量要少

    这里的依赖主要是秒杀系统和业务系统的区别在于,业务系统追求稳定,秒杀系统追求那一刻的效率。这也类似于CP和AP之间的选择。

    如下图所示,我们可以把它想象成一个尖峰场景。如果某项服务出现故障,是否会影响整个系统?肯定不行,所以这里要注意强依赖和弱依赖的问题。



    杜绝单点

    这个没什么好说的。一旦发生事故或停机,不仅会影响使用,还可能影响数据,所以我们必须用多服务、分布式和集群的思想来设计系统。

    学习淘宝

    淘宝早期秒杀系统架构

    要快速搭建一个简单的秒杀系统,只需要在你的产品购买页面添加一个“定时上架”功能,让用户只在秒杀开始时看到购买按钮,当产品库存售完时就会结束。这是当时钉钉系统实现的第一个版本。

    音量增加10w/s

    随着体量的增加,遇到了很多瓶颈。因此,将道钉模块分离成道钉系统。这样就可以对秒杀系统做一些针对性的优化。

    在部署方面,秒杀系统也可以独立部署在一个集群中,使得秒杀模块在不影响正常商品购买的机器负载的情况下,可以大流量枯竭。

    为了提高读取性能,减少与数据库的交互,将库存数量等热点数据单独放在一个缓存系统中。

    安全性方面,可以增加秒杀滑块,防止秒杀抢单,影响正常用户体验需求。

    音量的增加是100w/s

    在界面上做一些静态和动态的分离,让用户在杀的时候不需要刷新整个页面。

    秒杀产品在服务器端的本地缓存不需要调用依赖系统获取数据的后台服务,甚至不需要查询公共缓存集群中的数据,既可以减少系统调用,又可以避免碾压公共缓存集群。

    安全性方面,增加系统限流保护,防止最坏情况的发生。

    结尾

    建筑是一门平衡的艺术,一旦最好的建筑脱离了它所适应的场景,一切都将空谈。这里说的几点只是一个方向,你要尽量往这些方向努力,但也要考虑平衡其他因素。

    动静分离什么是动静数据

    动静分离不是真正的活数据,死数据。所谓“动静分离”,实际上是将用户请求的数据(如HTML页面)分为“动态数据”和“静态数据”。

    简单来说,“动态数据”与“静态数据”的主要区别在于页面中的输出数据是否与URL、查看者、时间、地域相关,是否包含Cookie等私有数据

  • 比如百度十大热搜,不管谁访问都一样。它是一个典型的静态数据,但却是一个动态接口。
  • 淘宝首页的商品会根据每个人的特点推送感兴趣的相关商品。这是动态数据,动态界面(但不典型,很多有推荐算法的app都有这种功能)
  • 动态和静态不是指数据本身是动态还是静态,而是数据中是否包含与访问者相关的个性化数据。

    静态数据优化

    在了解了动态数据和静态数据之后,我猜你脑子里已经有了一个优化方案。

  • 用户的静态数据可以缓存在Redis中,也可以缓存在离用户最近的地方。比如用户浏览器,CDN。
  • 直接缓存HTTP连接
  • 使用Web服务器处理大型并发静态文件请求。比如我们常用的nginx和apache。
  • 我估计很多人不理解直接缓存HTTP连接。下面介绍一下。静态转换是直接缓存HTTP,而不是缓存数据。Web代理服务器根据请求URL直接取出对应的HTTP响应头和响应体然后直接返回。这个响应过程非常简单,甚至连HTTP协议都不需要重新组装,甚至连HTTP请求头都不需要解析。

    动静分离改造

    以电子商务为例(淘宝,JD.COM)





    以博客为例(掘金,CSDN)





  • 我们可以缓存URL,使URL唯一。参见上述天猫、JD.COM、CSDN和掘金。缓存的密钥是唯一的数字id。
  • 商品/物品是动态的,但是每一个用户登录的信息验证是静态的,所以我们可以把服务的这部分分离出来。
  • 异步地理因素。与详细信息页面上的区域相关的因素是异步获取的。当然,您也可以通过动态请求来获取它们,但是在这里异步获取它们更合适。(无关数据)
  • 分离时间因子。服务器的输出时间也是通过动态请求获得的。
  • 下面两张参考图可以理解商品细节部分分离的思路。





    分离出动态内容后,我们可以对信息进行JSON(以JSON格式组织数据),方便前端采集。

    动态数据优化
  • ESI scheme(或SSI):在Web代理服务器上发出动态内容请求,并将请求插入到静态页面中。当用户得到页面时,它已经是一个完整的页面了。这种方式对服务器性能有一定影响,但用户体验更好。
  • CSI方案。也就是单独发起一个异步JavaScript请求,从服务器获取动态内容。这样服务器端性能更好,但用户端页面可能会延迟,体验稍差。
  • 动静分离的架构方案
  • 物理机单机部署;
  • 统一缓存层;
  • 上CDN。
  • 单一实体部署

    该方案将虚拟机改为物理机增加缓存容量,并采用一致哈希分组方法提高命中率。这里把缓存分成几组,希望达到命中率和访问热点的平衡。哈希包越少,缓存的命中率肯定越高。但短板也会把单一商品集中在一个包里,容易导致缓存崩溃。因此,我们应该适当地添加多个相同的数据包,以平衡访问热点和命中率的问题。

    优势

  • 没有网络瓶颈,可以使用大内存;
  • 既能提高命中率,又能减少Gzip压缩;
  • 减少缓存失效的压力,因为采用了定时失效的方式,比如缓存只有3秒,过期自动失效。
  • 缺点

  • 一定程度上也造成了CPU的浪费,因为单个Java进程很难用完整个实体机的CPU。
  • Java应用部署在实体机器上,作为缓存使用,导致运维复杂度高。
  • 如下图所示,单机部署的架构图



    统一缓存层

    所谓统一缓存层,是指将单机缓存统一分离,形成单个缓存集群。统一缓存层是比较理想的方案,可以推广。该方案的结构图如下



    优势

  • 当多个应用程序访问时,单个缓存层可以降低使用缓存的成本。这样访问的应用只需要维护自己的Java系统,不需要单独维护缓存,只关心如何使用。
  • 统一的缓存方案更容易维护,比如加强后期监控和配置的自动化,只需要一个解决方案,统一维护和升级也更方便。
  • 内存可以共享,最大限度的利用内存,不同系统之间的内存可以动态切换,可以有效应对各种攻击。
  • 缺点

  • 缓存层的交换网络成为瓶颈;
  • 服务器的缓存网卡也会是瓶颈;
  • 机器少风险大,挂一个会影响很大一部分缓存数据。
  • 要解决以上问题,可以对缓存进行哈希,即一组缓存的缓存内容相同,这样可以避免热点数据过于集中带来的新的瓶颈。

    在CDN上

    整个系统动静分离后,我们自然会想到更进一步的方案,就是把缓存进一步转发到CDN,因为CDN离用户最近,效果会更好。

    采用这种方案,有三个主要问题需要解决。

  • 故障问题
  • 问题命中率
  • 更新问题
  • 失效有点类似Redis。如果缓存没有及时更新,用户看到的值可能会在此期间放错位置。如果及时更新,就要保证CDN能够在几秒内同时使分布在全国各地的缓存失效。这个要求还是比较高的。

    命中率是缓存的生命线。有缓存系统的命中率太低,和没有缓存系统没什么区别。相反,它消耗自己的性能来查询缓存系统。

    综上所述,放产品详情,博客详情等不太现实。在中国所有的CDN节点上。我们可以采用以下解决方案来解决这一不足。

  • 靠近人流集中的区域。
  • 离主站比较远;
  • 节点与主站之间的网络良好稳定;
  • 节点容量比较大,不会占用其他cdn太多资源。
  • 不要有太多的节点。
  • 综合以上因素,选择CDN的二级缓存更合适,因为二级缓存数量更少,容量更大,这样用户的请求会先返回到源CDN的二级缓存,如果没有命中,会返回到源站获取数据。部署模式如下图所示:



    使用CDN的二级缓存作为缓存,可以达到类似当前服务器静态缓存的命中率,因为节点数量少,缓存不是很分散,访问相对集中,从而解决了命中率问题,给用户最好的访问体验,是目前比较理想的CDN解决方案。

    此外,CDN部署方案具有以下特点:

  • 在用户浏览器中缓存整个页面;
  • 如果整个页面被强制刷新,CDN也会被要求;
  • 实际的请求只是用户点击“刷新夺宝”按钮。
  • 这样,90%的静态数据都缓存在客户端或CDN中。当秒杀真的发生时,用户只需要点击专门的“刷新夺宝”按钮,而不需要刷新整个页面。这样,系统只向服务器请求少量的有效数据,而不是重复请求大量的静态数据。相比普通详情页的动态数据,秒杀动态数据更少,性能提升3倍以上。所以“抢宝”的设计思路让我们可以在不刷新页面的情况下,向服务器请求最新的动态数据。

    二八原则什么是二八原则

    世界上80%的财富掌握在20%的人手中,火热的数据也是如此。几千万的商品,几百万的商品,每天都有几十万的用户访问。这类数据就是热点数据

    在信息时代,并不是所有的数据都是热门的,所以在处理系统的热门时间时,我们可以分为两种情况。

  • 特定热门数据(如推荐产品)
  • 没有推荐数据,但是后期发酵成了热门数据。
  • 从冷静期到活跃期与活跃期

    从不是热点到成为热点最典型的例子就是今日头条,微博这样的app。如果一个新闻事件慢慢发酵,而系统中没有这个事件的缓存,那么系统可能很快就要宕机了。

    所以我们需要先找到热点。热点分为热点操作和热点数据。

  • 热点操作当用户在下拉模式下刷新时,他/她希望看到他/她正在关注的事件是否被热搜过。
  • 带热搜的热点数据事件应该是用户经常访问的。
  • 对于系统,是读请求写请求。这两种处理方法差别很大,但读取更容易处理,因为它可以减少与数据库的交互。写请求的瓶颈通常在存储层。后面会介绍。

    热点数据又分为动态热点数据(外界因素导致的热点商品)静态热点数据(商家推荐的商品)

    如何发现动态热点数据?
  • 搭建一个异步系统,可以收集交易环节每个环节中间件产品的热键,比如Nginx、cache、RPC服务框架等。(部分中间件产品已经有热点统计模块)。
  • 将上游系统采集的热点数据发送到热点服务台,然后下游系统(比如交易系统)就会知道哪些产品会被频繁调用,进而做热点保护。
  • 这是一个更大的系统,对于一个小系统来说。ELK scheme可以收集用户搜索商品的次数来判断是否是热点数据。

    如何处理动态热点数据?

    主要有三个思路。

  • 使最优化
  • 限制
  • 隔离;隔离
  • 优化

    最简单的优化方法是直接缓存数据。如果把热点数据和静态数据分开,静态数据可以缓存很长时间。然而,热数据的缓存更多的是“临时”缓存,即静态数据和动态数据都在队列中缓存几秒钟。由于队列长度有限,可以用LRU消去算法来代替。

    限值,电流限值

    限制,目前的限制更多的是一种保护机制,限制的方式有很多种,比如对被访问的商品的ID做一致的Hash,然后根据Hash做桶,为每个桶设置一个处理队列,从而将热门商品限制在一个请求队列中,防止其他请求因为某些热门商品占用过多的服务器资源而一直获得服务器的处理资源。

    隔离

    spike系统设计的首要原则是隔离这些热数据,不要让1%的请求影响到其他99%。隔离之后,优化这1%的请求就更方便了。

    结尾[/s2/]

    大概总结了一下

  • 如何设计道钉系统的五个原则
  • 动静分离方案
  • 两个原则,冷热数据处理方案

  • 作者:桓韶的成长之路
    链接:https://juejin.cn/post/7050760579480305701

    您可以还会对下面的文章感兴趣

    最新评论

    1. 长安常乐
      长安常乐
      发布于:2022-04-27 20:57:48 回复TA
      N。直接缓存HTTP连接使用Web服务器处理大型并发静态文件请求。比如我们常用的nginx和apache。我估计很多人不理解直接缓存HTTP连接。下面介绍一下。静态转换是直接缓存HTTP,而不是缓存数据。Web代理服务器根据请求UR
    1. 梦笑痴人
      梦笑痴人
      发布于:2022-04-27 13:31:05 回复TA
      到1,肯定不会。一点一点去研究淘宝10年前的技术发展过程当然不会划算。问题是,如何开发设计一个秒杀系统? 有这个想法的时候,我也是疯了。要点如下老板没有要求。我自己的事太忙了,不得不为自己的私活写一个函数。开发一个道钉,
    1. 神明替我护你
      神明替我护你
      发布于:2022-04-27 13:59:10 回复TA
      性能来查询缓存系统。综上所述,放产品详情,博客详情等不太现实。在中国所有的CDN节点上。我们可以采用以下解决方案来解决这一不足。靠近人流集中的区域。离主站比较远;节点与主站之间的网络良好稳定;节点容量比较大,不会占用其他cdn太多资源。不要有
    1. 苏艳中苑
      苏艳中苑
      发布于:2022-04-27 09:54:29 回复TA
      需要你的时候,你不吊我!你用到我的时候,喊爹都不帮你!
    1. 古仪盛玉
      古仪盛玉
      发布于:2022-04-27 09:54:29 回复TA
      每个人的长处和短处如同一枚钱币的两面,就看你把那一面翻出来。

    ◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

    使用微信扫描二维码后

    点击右上角发送给好友