秒杀系统架构设计_20***41

本文由用户“wjg761123”分享发布 更新时间:2020-02-21 18:31:44 举报文档

以下为《秒杀系统架构设计_20***41》的无排版文字预览,完整格式请下载

下载前请仔细阅读文字预览以及下方图片预览。图片预览是什么样的,下载的文档就是什么样的。

秒杀系统架构设计

秒杀系统架构设计都有哪些关键点?

你好,我是许某某,花名“XX”。说起来我的职业生涯算是比较简单,

2009 年大学毕业后就进入了淘宝,一直工作了七年多。这七年多的时间里,我有幸看到了淘宝业务的快速增长,并且以开发者的身份参与其中。

说实话,作为一名程序员,我的技术能力***业务的快速增长过程中得到了历练,并积累了一些大流量高并发网站架构设计和优化的经验,尤其是针对“秒杀”这个场景。因为我确信,那个时候我们肯定是对系统做了足够多的极致优 化,才能扛住当时洪峰般的流量请求。

记得早期的时候,淘宝商品详情系统的 PV 还差不多是 1 亿的样子,但是到

2016 年差不多已经升至 50 亿了。尤其是 2012 年到 2014 年那个时间

段,“秒杀”活动特别流行,用户的参与热情一浪高过一浪,系统要面对的流量也是成倍增长。

而每一次的秒杀活动对技术团队来说都是一次考验。现在想起来,那个时候我们整个团队,无所畏惧,逐步迭代创新,然后解决一个个难题的过程,也是极具挑战性和成就感的事情。

记得有一年,为了应对“双十一”,我们整个商品详情团队对系统做了很多 优化,我们自认为已经是***最牛的系统了,性能也已经是“业界之巅”。

但是那年“双十一”的晚上,我们的系统还是遇到了瓶颈。当时老大就跑过来盯着我们,问我们什么时候能够恢复,我们整个团队都承担着巨大的心理压力。

事后我们复盘宕机的原因,发现当时的秒杀流量远远超过了我们的预想,我 们根本没想到大家的参与热情能有那么高。于是我们按照这个增长率去预估下一年的流量和服务器,粗算下来,我记得差不多要增加 2000 台服务器,简直不可思议。

怎么可能真正增加这么多机器,所以这也就倒逼我们必须找出一些特殊的手 段来优化系统。后面,经过一段时间的调研和分析,我们想到了把整个系统进行动静分离改造的解决方案。

秒杀系统也差不多那个时候才从商品详情系统独立出来成为一个独立产品 的。因为我见证了秒杀系统的建设过程,所以也有颇多感慨。秒杀系统的迭代又是一个升级打怪的过程,我们也都是遇到问题解决问题,逐一优化。

那么,如何才能更好地理解秒杀系统呢?我觉得作为一个程序员,你首先需 要从高维度出发,从整体XX考问题。在我看来,秒杀其实主要解决两个问题, 一个是并发读,一个是并发写。并发读的核心优化理念是尽量减少用户到服务端来“读”数据,或者让他们读更少的数据;并发写的处理原则也一样,它要求我们在数据库层面独立出来一个库,做特殊的处理。另外,我们还要针对秒杀系统做一些保护,针对意料之外的情况设计兜底方案,以防止最坏的情况发生。

而从一个架构师的角度来看,要想打造并维护一个超大流量并发读写、高性 能、高某某的系统,在整个用户请求路径上从浏览器到服务端我们要遵循几个原则,就是要保证用户请求的数据尽量少、请求数尽量少、路径尽量短、依赖尽量少,并且不要有单点。这些关键点我会在后面的文章里重点讲解。

其实,秒杀的整体架构可以概括为“稳、准、快”几个关键字。

所谓“稳”,就是整个系统架构要满足高某某,流量符合预期时肯定要稳定,就是超出预期时也同样不能掉链子,你要保证秒杀活动顺利完成,即秒杀商品顺利地卖出去,这个是最基本的前提。

然后就是“准”,就是秒杀 10 台 iPhone,那就只能成交 10 台,多一台少一台都不行。一旦库存不对,那平台就要承担损失,所以“准”就是要求保证数据的一致性。

最后再看“快”,“快”其实很好理解,它就是说系统的性能要足够高,否则你怎么支撑这么大的流量呢?不光是服务端要做极致的性能优化,而且在整个请求链路上都要做协同的优化,每个地方快一点,整个系统就完美了。

所以从技术角度上看“稳、准、快”,就对应了我们架构上的高某某、一致性和高某某的要求,我们的专栏也将主要围绕这几个方面来展开,具体如下。

高某某。 秒杀涉及大量的并发读和并发写,因此支持高并发访问这点非常关键。本专栏将从设计数据的动静分离方案、热点的发现与隔离、请 求的削峰与分层过滤、服务端的极致优化这 4 个方面重点介绍。

一致性。 秒杀中商品减库存的实现方式同样关键。可想而知,有限数量的商品在同一时刻被很多倍的请求同时来减库存,减库存又分为“拍下 减库存”“付款减库存”以及预扣等几种,在大并发更新的过程中都要保 证数据的准确性,其难度可想而知。因此,我将用一篇文章来专门讲解如 何设计秒杀减库存方案。

高某某。 虽然我介绍了很多极致的优化思路,但现实中总难免出现一些我们考虑不到的情况,所以要保证系统的高某某和正确性,我们还要设 计一个 PlanB 来兜底,以便在最坏情况发生时仍然能够从容应对。专栏的最后,我将带你思考可以从哪些环节来设计兜底方案。

最后,很幸运能在极客时间遇到你,希望这堂课能让你彻底理解大并发、高性 能、高某某秒杀系统的设计之道,并能够在思考解决类似问题时有更准确的思考和判断。

| 设计秒杀系统时应该注意的5个架构原则

2018-10-01 许某某

/



说起秒杀,我想你肯定不陌生,这两年,从双十一购物到春节抢红包,再到

12306 抢火车票,“秒杀”的场景处处可见。简单来说,秒杀就是在同一个时刻有大量的请求争抢购买同一个商品并完成交易的过程,用技术的行话来说就是大量的并发读和并发写。

不管是哪一门语言,并发都是程序员们最为头疼的部分。同样,对于一个软件而言也是这样,你可以很快增删改查做出一个秒杀系统,但是要让它支持高并发访问就没那么容易了。比如说,如何让系统面对百万级的请求流量不出故障?如何保证高并发情况下数据的一致性写?完全靠堆服务器来解决吗?这显然不是最好的解决方案。

在我看来,秒杀系统本质上就是一个满足大并发、高某某和高某某的分布式系 统。今天,我们就来聊聊,如何在满足一个良好架构的分布式系统基础上,针对秒杀这种业务做到极致的性能改进。

架构原则:“4 要 1 不要”

如果你是一个架构师,你首先要勾勒出一个轮廓,想一想如何构建一个超大流量

并发读写、高某某,以及高某某的系统,这其中有哪些要素需要考虑。我把这些要素总结为“4 要 1 不要”。

数据要尽量少

所谓“数据要尽量少”,首先是指用户请求的数据能少就少。请求的数据包括上传给系统的数据和系统返回给用户的数据(通常就是网页)。

为啥“数据要尽量少”呢?因为首先这些数据在网络上传输需要时间,其次不管是请求数据还是返回数据都需要服务器做处理,而服务器在写网络时通常都要做压缩和字符编码,这些都非常消耗 CPU,所以减少传输的数据量可以显著减少

CPU 的使用。例如,我们可以简化秒杀页面的大小,去掉不必要的页面装修效果,等等。

其次,“数据要尽量少”还要求系统依赖的数据能少就少,包括系统完成某些业务逻辑需要读取和保存的数据,这些数据一般是和后台服务以及数据库打交道 的。调用其他服务会涉及数据的序列化和反序列化,而这也是 CPU 的一大杀

手,同样也会增加延时。而且,数据库本身也容易成为一个瓶颈,所以和数据库打交道越少越好,数据越简单、越小则越好。

请求数要尽量少

用户请求的页面返回后,浏览器渲染这个页面还要包含其他的额外请求,比如 说,这个页面依赖的 CSS/JavaScript、图片,以及 Ajax 请求等等都定义为“额外请求”,这些额外请求应该尽量少。因为浏览器每发出一个请求都多少会有一些消耗,例如建立连接要做三次握手,有的时候有页面依赖或者连接数限制,一些请求(例如 JavaScript)还需要串行加载等。另外,如果不同请求的域名不一样的话,还涉及这些域名的 DNS 解析,可能会耗时更久。所以你要记住的是,减少请求数可以显著减少以上这些因素导致的资源消耗。

例如,减少请求数最常用的一个实践就是合并 CSS 和 JavaScript 文件,把多个

JavaScript 文件合并成一个文件,在 URL 中用逗号隔开

(https://g.xxx.com/tm/xx-b/4.0.94/mods/??module- preview/index.xtpl.js,module-jhs/index.xtpl.js,module-

focus/index.xtpl.js)。这种方式在服务端仍然是单个文件各自存放,只是服务端会有一个组件解析这个 URL,然后动态把这些文件合并起来一起返回。

路径要尽量短

所谓“路径”,就是用户发出请求到返回数据这个过程中,需求经过的中间的节点数。

通常,这些节点可以表示为一个系统或者一个新的 Socket 连接(比如代理服务器只是创建一个新的 Socket 连接来转发请求)。每经过一个节点,一般都会产生一个新的 Socket 连接。

然而,每增加一个连接都会增加新的不确定性。从概率统计上来说,加入一次请求经过 5 个节点,每个节点的可用性是 99.9% 的话,那么整个请求的可用性

是:99.9% 的 5 次方,约等于 99.5%。

所以缩短请求路径不仅可以增加可用性,同样可以有效提升性能(减少中间节点可以减少数据的序列化与反序列化),并减少延时(可以减少网络传输耗时)。要缩短访问路径有一种办法,就是多个相互强依赖的应用合并部署在一起,把远程过程调用(RPC)变成 JVM 内部之间的方法调用。在《大型网站技术架构演进与性能优化》一书中,我也有一章介绍了这种技术的详细实现。

依赖要尽量少

所谓依赖,指的是要完成一次用户请求必须依赖的系统或者服务,这里的依赖指的是强依赖。

举个例子,比如说你要展示秒杀页面,而这个页面必须强依赖商品信息、用户信息,还有其他如优惠券、成交列表等这些对秒杀不是非要不可的信息(弱依

赖),这些弱依赖在紧急情况下就可以去掉。

要减少依赖,我们可以给系统进行分级,比如 0 级系统、1 级系统、2 级系统、

3 级系统,0 级系统如果是最重要的系统,那么 0 级系统强依赖的系统也同样是最重要的系统,以此类推。

注意,0 级系统要尽量减少对 1 级系统的强依赖,防止重要的系统被不重要的系统拖垮。例如支付系统是 0 级系统,而优惠券是 1 级系统的话,在极端情况

下可以把优惠券给降级,防止支付系统被优惠券这个 1 级系统给拖垮。

不要有单点

系统中的单点可以说是系统架构上的一个大忌,因为单点意味着没有备份, 风险不可控,我们设计分布式系统最重要的原则就是“消除单点”。

那如何避免单点呢?我认为关键点是避免将服务的状态和机器绑定,即把服务无状态化,这样服务就可以在机器中随意移动。

如何那把服务的状态和机器解耦呢?这里也有很多实现方式。例如把和机器 相关的配置动态化,这些参数可以通过配置中心来动态推送,在服务启动时动态拉取下来,我们在这些配置中心设置一些规则来方便地改变这些映射关系。

应用无状态化是有效避免单点的一种方式,但是像存储服务本身很难无状态 化,因为数据要存储在磁盘上,本身就要和机器绑定,那么这种场景一般要通过冗余多个备份的方式来解决单点问题。

前面介绍了这些设计上的一些原则,但是你有没有发现,我一直说的是“尽量”而不是“绝对”?

我想你肯定会问是不是请求最少就一定最好,我的答案是“不一定”。我们曾经把有些 CSS 内联进页面里,这样做可以减少依赖一个 CSS 的请求从而加快首页的渲染,但是同样也增大了页面的大小,又不符合“数据要尽量少”的原 则,这种情况下我们为了提升首屏的渲染速度,只把首屏的 HTML 依赖的 CSS 内联进来,其他 CSS 仍然放到文件中作为依赖加载,尽量实现首屏的打开速度与整个页面加载性能的平衡。

所以说,架构是一种平衡的艺术,而最好的架构一旦脱离了它所适应的场 景,一切都将是空谈。我希望你记住的是,这里所说的几点都只是一个个方向, 你应该尽量往这些方向上去努力,但也要考虑平衡其他因素。

不同场景下的不同架构案例

前面我说了一些架构上的原则,那么针对“秒杀”这个场景,怎样才是一个好的

架构呢?下面我以淘宝早期秒杀系统架构的演进为主线,来帮你梳理不同的请求体量下,我认为的最佳秒杀系统架构。

如果你想快速搭建一个简单的秒杀系统,只需要把你的商品购买页面增加一

个“定时上架”功能,仅在秒杀开始时才让用户看到购买按钮,当商品的库存卖完了也就结束了。这就是当时第一个版本的秒杀系统实现方式。

但随着请求量的加大(比如从 1w/s 到了 10w/s 的量级),这个简单的架构很快就遇到了瓶颈,因此需要做架构改造来提升系统性能。这些架构改造包括:

把秒杀系统独立出来单独打造一个系统,这样可以有针对性地做优化, 例如这个独立出来的系统就减少了店铺装修的功能,减少了页面的复杂

度;

在系统部署上也独立做一个机器集群,这样秒杀的大流量就不会影响到正常的商品购买集群的机器负载;

将热点数据(如库存数据)单独放到一个缓存系统中,以提高“读性能”;

增加秒杀答题,防止有秒杀器抢单。

此时的系统架构变成了下图这个样子。最重要的就是,秒杀详情成为了一个独立的新系统,另外核心的一些数据放到了缓存(Cache)中,其他的关联系统也都以独立集群的方式进行部署。

图 1 改造后的系统架构

然而这个架构仍然支持不了超过 100w/s 的请求量,所以为了进一步提升秒杀系统的性能,我们又对架构做进一步升级,比如:

对页面进行彻底的动静分离,使得用户秒杀时不需要刷新整个页面,而只需要点击抢宝按钮,借此把页面刷新的数据降到最少;

在服务端对秒杀商品进行本地缓存,不需要再调用依赖系统的后台服务获取数据,甚至不需要去公共的缓存集群中查询数据,这样不仅可以减少系统调用,而且能够避免压垮公共缓存集群。

增加系统限流保护,防止最坏情况发生。

经过这些优化,系统架构变成了下图中的样子。在这里,我们对页面进行了进一步的静态化,秒杀过程中不需要刷新整个页面,而只需要向服务端请求很少的动态数据。而且,最关键的详情和交易系统都增加了本地缓存,来提前缓存秒杀商品的信息,热点数据库也做了独立部署,等等。

图 2 进一步改造后的系统架构

从前面的几次升级来看,其实越到后面需要定制的地方越多,也就是越“不通 用”。例如,把秒杀商品缓存在每台机器的内存中,这种方式显然不适合太多的商品同时进行秒杀的情况,因为单机的内存始终有限。所以要取得极致的性能, 就要在其他地方(比如,通用性、易用性、成本等方面)有所牺牲。

总结

来让我们回顾下前面的内容,我首先介绍了构建大并发、高某某、高某某系

统中几种通用的优化思路,并抽象总结为“4 要 1 不要”原则,也就是:数据要尽量少、请求数要尽量少、路径要尽量短、依赖要尽量少,以及不要有单点。

当然,这几点是你要努力的方向,具体操作时还是要密切结合实际的场景和具体条件来进行。

然后,我给出了实际构建秒杀系统时,根据不同级别的流量,由简单到复杂 打造的几种系统架构,希望能供你参考。当然,这里面我没有说具体的解决方 案,比如缓存用什么、页面静态化用什么,因为这些对于架构来说并不重要,作为架构师,你应该时刻提醒自己主线是什么。

说了这么多,总体上我希望给你一个方向,就是想构建大并发、高某某、高 可用的系统应该从哪几个方向上去努力,然后在不同性能要求的情况下系统架构应该从哪几个方面去做取舍。同时你也要明白,越追求极致性能,系统定制开发就会越多,同时系统的通用性也就会越差。

最后,欢迎你在评论区和我分享你在设计秒杀系统时的一些经验和思考,你的经验对我们这个专栏来说也很重要。

| 如何才能做好动静分离?有哪些方案可选?

2018-10-02 许某某

/



上一篇文章中,我介绍了秒杀系统在架构上要考虑的几个原则,我估计你很 快就会问:“知易行难,这些原则应该怎么应用到系统中呢?”别急,从这篇文章开始,我就会逐一介绍秒杀系统的各个关键环节中涉及的关键技术。

今天我们就先来讨论第一个关键点:数据的动静分离。不知道你之前听过这 个解决方案吗?不管你有没有听过,我都建议你先停下来思考动静分离的价值。如果你的系统还没有开始应用动静分离的方案,那你也可以想想为什么没有,是之前没有想到,还是说业务体量根本用不着?

不过我可以确信地说,如果你在一个业务飞速发***里,并且你在深度 ***内类秒杀类系统的架构或者开发工作,那么你迟早会想到动静分离的方案。为什么?很简单,秒杀的场景中,对于系统的要求其实就三个字:快、准、稳。

那怎么才能“快”起来呢?我觉得抽象起来讲,就只有两点,一点是提高单 次请求的效率,一点是减少没必要的请求。今天我们聊到的“动静分离”其实就是瞄着这个大方向去的。

不知道你是否还记得,最早的秒杀系统其实是要刷新整体页面的,但后来秒杀的时候,你只要点击“刷新抢宝”按钮就够了,这种变化的本质就是动静分 离,分离之后,客户端大幅度减少了请求的数据量。这不自然就“快”了吗?

何为动静数据

那到底什么才是动静分离呢?所谓“动静分离”,其实就是把用户请求的数据

(如 HTML 页面)划分为“动态数据”和“静态数据”。

简单来说,“动态数据”和“静态数据”***输出的数据是否和 URL、浏览者、时间、地域相关,以及是否含有 Cookie 等私密数据。比如说:

很多媒体类的网站,某一篇文章的内容不管是你访问还是我访问,它都是一样的。所以它就是一个典型的静态数据,但是它是个动态页面。

我们如果现在访问淘宝的首页,每个人看到的页面可能都是不一样的, 淘宝首页中包含了很多根据访问者特征推荐的信息,而这些个性化的数据就可以理解为动态数据了。

这里再强调一下,我们所说的静态数据,不能仅仅理解为传统意义上完全存在磁盘上的 HTML 页面,它也可能是经过 Java 系统产生的页面,但是它输出的页面本身不包含上面所说的那些因素。也就是所谓“动态”还是“静态”,并不是说数据本身是否动静,而是数据中是否含有和访问者相关的个性化数据。

还有一点要注意,就是页面中“不包含”,指的是“页面的 HTML 源码中不含有”,这一点务必要清楚。

理解了静态数据和动态数据,我估计你很容易就能想明白“动静分离”这个方案的来龙去脉了。分离了动静数据,我们就可以对分离出来的静态数据做缓 存,有了缓存之后,静态数据的“访问效率”自然就提高了。

那么,怎样对静态数据做缓存呢?我在这里总结了几个重点。

第一,你应该把静态数据缓存到离用户最近的地方。静态数据就是那些相对不会变化的数据,因此我们可以把它们缓存起来。缓存到哪里呢?常见的就三种,用户浏览器里、CDN 上或者在服务端的 Cache 中。你应该根据情况,把它们尽量缓存到离用户最近的地方。

第二,静态化改造就是要直接缓存 HTTP 连接。相较于普通的数据缓存而言, 你肯定还听过系统的静态化改造。静态化改造是直接缓存 HTTP 连接而不是仅仅缓存数据,如下图所示,Web 代理服务器根据请求 URL,直接取出对应的

HTTP 响应头和响应体然后直接返回,这个响应过程简单得连 HTTP 协议都不用重新组装,甚至连 HTTP 请求头也不需要解析。

图 1 静态化改造

第三,让谁来缓存静态数据也很重要。不同语言写的 Cache 软件处理缓存数据的效率也各不相同。以 Java 为例,因为 Java 系统本身也有其弱点(比如不擅长处理大量连接请求,每个连接消 内容过长,仅展示头部和尾部部分文字预览,全文请查看图片预览。 常态的压力体系,例如上线前的单机压测到上线后的全链路压测)、管控(做好线上运行时的降级、限流和兜底保护)、监控(建立性能基线来记录性能的变化趋势以及线上机器的负载报警体系,发现问题及时预警)和恢复体系(遇到故障要及时止损,并提供快速的数据订正工具等)等这些地方加强建设,每一个环节可能都有很多事情要做。

另外,要保证高某某建设的落实,你不仅要做系统建设,还要在组织上做好 保障。高某某其实就是在说“稳定性”。稳定性是一个平时不重要,但真出了问题就会要命的事儿,所以很可能平时业务发展良好,稳定性建设就会给业务让 路,相关的稳定性负责人员平时根本得不到重视,一旦遇到故障却又成了“背锅侠”。

而要防止出现这种情况,就必须在组织上有所保障,例如可以让业务负责人背上稳定性 KPI 考核指标,然后在技术部门中建立稳定性建设小组,小组成员由每个业务线的核心力量兼任,他们的 KPI 由稳定性负责人来打分,这样稳定 性小组就可以把一些体系化的建设任务落实到具体的业务系统中了。

最后,欢迎你在留言区和我交流,你也可以说说在实际工作中,还有哪些关于系统稳定性建设方面有更好的思路或者方案,我们一起沟通探讨。

[文章尾部最后500字内容到此结束,中间部分内容请查看底下的图片预览]请点击下方选择您需要的文档下载。

  1. 防疫开学第一课教 我在春XX你
  2. 健康睡眠教案
  3. 《在幻灯片中添加文字和插入图片》课堂实录
  4. 广电期末个人总结
  5. (最终定稿)县深入推进禁毒工作成就展示专题片解说词(1.11)2
  6. 教育机构复课告知书
  7. 教授健康讲座
  8. 抖音具体养号方法
  9. “GTP格式硬盘安装器”重装教程
  10. 小学二年级作文:疫情来了
  11. 学院班会记录表(1)
  12. 教育笔记
  13. 银行柜台新员工培训心得
  14. 新学期高校思想动态调研话题
  15. 征文保护水资源,从我做起
  16. 观看优秀大学生励志成长宣讲报告会心得体会
  17. 2020小学开学典礼校长发言
  18. 《管理学基础》形成性考核任务

以上为《秒杀系统架构设计_20***41》的无排版文字预览,完整格式请下载

下载前请仔细阅读上面文字预览以及下方图片预览。图片预览是什么样的,下载的文档就是什么样的。

图片预览