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

说起秒杀,我想你肯定不陌生,这两年,从双十一购物到春节抢红包,再到 12306 抢火车 票,“秒杀”的场景处处可见。简单来说,秒杀就是在同一个时刻有大量的请求争抢购买同一个 商品并完成交易的过程,用技术的行话来说就是大量的并发读和并发写。

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

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

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

如果你是一个架构师,你首先要勾勒出一个轮廓,想一想如何构建一个超大流量并发读写、高性 能,以及高可用的系统,这其中有哪些要素需要考虑。我把这些要素总结为“4 要 1 不要”。

1. 数据要尽量少

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

为啥“数据要尽量少”呢?因为首先这些数据在网络上传输需要时间,其次不管是请求数据还是 返回数据都需要服务器做处理,而服务器在写网络时通常都要做压缩和字符编码,这些都非常消 耗 CPU,所以减少传输的数据量可以显著减少 CPU 的使用。例如,我们可以简化秒杀页面的大 小,去掉不必要的页面装修效果,等等。

其次,“数据要尽量少”还要求系统依赖的数据能少就少,包括系统完成某些业务逻辑需要读取 和保存的数据,这些数据一般是和后台服务以及数据库打交道的。调用其他服务会涉及数据的序 列化和反序列化,而这也是 CPU 的一大杀手,同样也会增加延时。而且,数据库本身也容易成 为一个瓶颈,所以和数据库打交道越少越好,数据越简单、越小则越好。

2. 请求数要尽量少

用户请求的页面返回后,浏览器渲染这个页面还要包含其他的额外请求,比如说,这个页面依赖 的 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,然后动态把这 些文件合并起来一起返回。

3. 路径要尽量短

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

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

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

所以缩短请求路径不仅可以增加可用性,同样可以有效提升性能(减少中间节点可以减少数据的 序列化与反序列化),并减少延时(可以减少网络传输耗时)。

要缩短访问路径有一种办法,就是多个相互强依赖的应用合并部署在一起,把远程过程调用 (RPC)变成 JVM 内部之间的方法调用。在《大型网站技术架构演进与性能优化》一书中,我 也有一章介绍了这种技术的详细实现。

4. 依赖要尽量少

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

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

要减少依赖,我们可以给系统进行分级,比如 0 级系统、1 级系统、2 级系统、3 级系统,0 级 系统如果是最重要的系统,那么 0 级系统强依赖的系统也同样是最重要的系统,以此类推。 注意,0 级系统要尽量减少对 1 级系统的强依赖,防止重要的系统被不重要的系统拖垮。例如支 付系统是 0 级系统,而优惠券是 1 级系统的话,在极端情况下可以把优惠券给降级,防止支付系 统被优惠券这个 1 级系统给拖垮。

5. 不要有单点

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

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

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

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

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

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

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

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

前面我说了一些架构上的原则,那么针对“秒杀”这个场景,怎样才是一个好的架构呢?下面我 以淘宝早期秒杀系统架构的演进为主线,来帮你梳理不同的请求体量下,我认为的最佳秒杀系统 架构。

如果你想快速搭建一个简单的秒杀系统,只需要把你的商品购买页面增加一个“定时上架”功 能,仅在秒杀开始时才让用户看到购买按钮,当商品的库存卖完了也就结束了。这就是当时第一 个版本的秒杀系统实现方式

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

1. 把秒杀系统独立出来单独打造一个系统,这样可以有针对性地做优化,例如这个独立出来的系 统就减少了店铺装修的功能,减少了页面的复杂度; 2. 在系统部署上也独立做一个机器集群,这样秒杀的大流量就不会影响到正常的商品购买集群的 机器负载; 3. 将热点数据(如库存数据)单独放到一个缓存系统中,以提高“读性能”; 4. 增加秒杀答题,防止有秒杀器抢单。

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

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

改造后的系统架构

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

  1. 对页面进行彻底的动静分离,使得用户秒杀时不需要刷新整个页面,而只需要点击抢宝按钮, 借此把页面刷新的数据降到最少;
  2. 在服务端对秒杀商品进行本地缓存,不需要再调用依赖系统的后台服务获取数据,甚至不需要 去公共的缓存集群中查询数据,这样不仅可以减少系统调用,而且能够避免压垮公共缓存集 群。
  3. 增加系统限流保护,防止最坏情况发生。

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

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

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

总结

来让我们回顾下前面的内容,我首先介绍了构建大并发、高性能、高可用系统中几种通用的优化 思路,并抽象总结为“4 要 1 不要”原则,也就是:数据要尽量少、请求数要尽量少、路径要尽 量短、依赖要尽量少,以及不要有单点。当然,这几点是你要努力的方向,具体操作时还是要密 切结合实际的场景和具体条件来进行。

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

说了这么多,总体上我希望给你一个方向,就是想构建大并发、高性能、高可用的系统应该从哪 几个方向上去努力,然后在不同性能要求的情况下系统架构应该从哪几个方面去做取舍。同时你 也要明白,越追求极致性能,系统定制开发就会越多,同时系统的通用性也就会越差。
欢迎工作一到五年的Java工程师朋友们加入Java架构开发:810589193
群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容