每秒100W请求,12306秒杀业务,架构如何优化?
如《同样是高并发,QQ/微博/12306的架构难度一样吗?》一文所述,同样是高并发场景,三类业务的架构挑战不一样:
- QQ类业务,用户主要读写自己的数据,访问基本带有uid属性,数据访问锁冲突较小
- 微博类业务,用户的feed主页由别人发布的消息构成,数据读写有一定锁冲突
- 12306类业务,并发量很高,几乎所有的读写锁冲突都集中在少量数据上,难度最大
那么对于秒杀类业务,系统上和业务上分别能如何优化呢,这是本文要讨论的问题。
系统层面,秒杀业务的优化方向如何?
主要有两项:
(1)将请求尽量拦截在系统上游,而不要让锁冲突落到数据库。
传统秒杀系统之所以挂,是因为请求都压到了后端数据层,数据读写锁冲突严重,并发高响应慢,几乎所有请求都超时,访问流量大,下单成功的有效流量小。
一趟火车2000张票,200w个人同时来买,没有人能买成功,请求有效率为0。
画外音:此时系统的效率,还不如线下售票窗口。
(2)充分利用缓存。
秒杀买票,这是一个典型的读多写少的业务场景:
- 车次查询,读,量大
- 余票查询,读,量大
- 下单和支付,写,量小
一趟火车2000张票,200w个人同时来买,最多2000个人下单成功,其他人都是查询库存,写比例只有0.1%,读比例占99.9%,非常适合使用缓存来优化。
秒杀业务,常见的系统分层架构如何?

秒杀业务,可以使用典型的服务化分层架构:
- 端(浏览器/APP),最上层,面向用户
- 站点层,访问后端数据,拼装html/json返回
- 服务层,屏蔽底层数据细节,提供数据访问
- 数据层,DB存储库存,当然也有缓存
这四层分别应该如何优化呢?
一、端上的请求拦截(浏览器/APP)
想必春节大家都玩过微信的摇一摇抢红包,用户每摇一次,真的就会往后端发送一次请求么?
回顾抢票的场景,用户点击“查询”按钮之后,系统卡顿,用户着急,会不自觉的再去频繁点击“查询”,不但没用,反而平白无故增加系统负载,平均一个用户点5次,80%的请求是这么多出来的。
JS层面,可以限制用户在x秒之内只能提交一次请求,从而降低系统负载。
画外音:频繁提交,可以友好提示“频率过快”。
APP层面,可以做类似的事情,虽然用户疯狂的在摇微信抢红包,但其实x秒才向后端发起一次请求。
画外音:这就是所谓的“将请求尽量拦截在系统上游”,浏览器/APP层就能拦截80%+的请求。
不过,端上的拦截只能挡住普通用户(99%的用户是普通用户),程序员firebug一抓包,写个for循环直接调用后端http接口,js拦截根本不起作用,这下怎么办?
二、站点层的请求拦截
如何抗住程序员写for循环调用http接口,首先要确定用户的唯一标识,对于频繁访问的用户予以拦截。
用什么来做用户的唯一标识?
ip?cookie-id?别想得太复杂,购票类业务都需要登录,用uid就能标识用户。
在站点层,对同一个uid的请求进行计数和限速,例如:一个uid,5秒只准透过1个请求,这样又能拦住99%的for循环请求。
一个uid,5s只透过一个请求,其余的请求怎么办?
缓存,页面缓存,5秒内到达站点层的其他请求,均返回上次返回的页面。
画外音:车次查询和余票查询都能够这么做,既能保证用户体验(至少没有返回404页面),又能保证系统的健壮性(利用页面缓存,把请求拦截在站点层了)。
OK,通过计数、限速、页面缓存拦住了99%的普通程序员,但仍有些高端程序员,例如黑客,控制了10w个肉鸡,手里有10w个uid,同时发请求,这下怎么办?
三、服务层的请求拦截
并发的请求已经到了服务层,如何进拦截?
服务层非常清楚业务的库存,非常清楚数据库的抗压能力,可以根据这两者进行削峰限速。
例如,业务服务很清楚的知道,一列火车只有2000张车票,此时透传10w个请求去数据库,是没有意义的。
画外音:假如数据库每秒只能抗500个写请求,就只透传500个。
用什么削峰?
请求队列。
对于写请求,做请求队列,每次只透传有限的写请求去数据层(下订单,支付这样的写业务)。
只有2000张火车票,即使10w个请求过来,也只透传2000个去访问数据库:
- 如果前一批请求均成功,再放下一批
- 如果前一批请求库存已经不足,则后续请求全部返回“已售罄”
对于读请求,怎么优化?
cache抗,不管是memcached还是redis,单机抗个每秒10w应该都是没什么问题的。
画外音:缓存做水平扩展,很容易线性扩容。
如此削峰限流,只有非常少的写请求,和非常少的读缓存mis的请求会透到数据层去,又有99%的请求被拦住了。
四、数据库层
经过前三层的优化:
- 浏览器拦截了80%请求
- 站点层拦截了99%请求,并做了页面缓存
- 服务层根据业务库存,以及数据库抗压能力,做了写请求队列与数据缓存
你会发现,每次透到数据库层的请求都是可控的。
db基本就没什么压力了,闲庭信步。
画外音:这类业务数据量不大,无需分库,数据库做一个高可用就行。
此时,透2000个到数据库,全部成功,请求有效率100%。
画外音:优化前,10w个请求0个成功,有效性0%。
按照上面的优化方案,其实压力最大的反而是站点层,假设真实有效的请求数是每秒100w,这部分的压力怎么处理?
解决方向有两个:
(1)站点层水平扩展,通过加机器扩容,一台抗5000,200台搞定;
(2)服务降级,抛弃请求,例如抛弃50%;
原则是要保护系统,不能让所有用户都失败。
站点层限速,是个每个uid的请求计数放到redis里么?吞吐量很大情况下,高并发访问redis,网络带宽会不会成为瓶颈?
同一个uid计数与限速,如果担心访问redis带宽成为瓶颈,可以这么优化:
(1)计数直接放在内存,这样就省去了网络请求;
(2)在nginx层做7层均衡,让一个uid的请求落到同一个机器上;
画外音:这个计数对数据一致性、准确性要求不高,即使服务重启计数丢了,大不了重新开始计。
除了系统上的优化,产品与业务还能够做一些折衷,降低架构难度。
业务折衷一
一般来说,下单和支付放在同一个流程里,能够提高转化率。对于秒杀场景,产品上,下单流程和支付流程异步,放在两个环节里,能够降低数据库写压力。以12306为例,下单成功后,系统占住库存,45分钟之内支付即可。
业务折衷二
一般来说,所有用户规则相同,体验会更好。对于秒杀场景,产品上,不同地域分时售票,虽然不是所有用户规则相同,但能够极大降低系统压力。北京9:00开始售票,上海9:30开始售票,广州XX开始售票,能够分担系统压力。
业务折衷三
秒杀场景,由于短时间内并发较大,系统返回较慢,用户心情十分焦急,可能会频繁点击按钮,对系统造成压力。产品上可以优化为,一旦点击,不管系统是否返回,按钮立刻置灰,不给用户机会频繁点击。
业务折衷四
一般来说,显示具体的库存数量,能够加强用户体验。对于秒杀场景,产品上,只显示有/无车票,而不是显示具体票数目,能够降低缓存淘汰率。
画外音:显示库存会淘汰N次,显示有无只会淘汰1次。更多的,用户关注是否有票,而不是票有几张。
无论如何,产品技术运营一起,目标是一致的,把事情做好,不存在谁是甲方,谁是乙方的关系。
总结
对于秒杀系统,除了产品和业务上的折衷,架构设计上主要有两大优化方向:
(1)尽量将请求拦截在系统上游;
(2)读多写少用缓存;
任何脱离业务的架构设计是耍流氓。

欢迎关注公众号:“Java架构师学习”
你会喜欢的!
每秒100W请求,12306秒杀业务,架构如何优化?的更多相关文章
- SSM框架学习之高并发秒杀业务--笔记5-- 并发优化
前几节终于实现了这个高并发秒杀业务,现在问题是如何优化这个业务使其能扛住一定程度的并发量. 一. 优化分析 对于整个业务来说,首先是分析哪些地方会出现高并发,以及哪些地方会影响到了业务的性能.可能会出 ...
- QPS从0到4000请求每秒,谈达达后台架构演化之路(转载)
https://blog.csdn.net/czbing308722240/article/details/52350219 QPS从0到4000请求每秒,谈达达后台架构演化之路 达达是全国领先的 ...
- SSM框架学习之高并发秒杀业务--笔记4-- web层
在前面几节中已经完成了service层和dao层,到目前为止只是后端的设计与编写,这节就要设计到前端的设计了.下面开始总结下这个秒杀业务前端有哪些要点: 1. 前端页面的流程 首先是列表页,点某个商品 ...
- 《京东B2B业务架构演变》阅读笔记
一.京东 B2B 业务的定位 让各类型的企业都可以在京东的 B 平台上进行采购.建立采购关系. 京东 B2B 的用户群体主要分为 2 类: 一类是大 B 用户.另一类是小 B 用户.京东 B 平台需要 ...
- 《京东B2B业务架构演变》阅读
转载:https://mp.weixin.qq.com/s/5xmmuw8O-I_Fi5bzE-_baA?tdsourcetag=s_pcqq_aiomsg 京东 B2B 业务的定位是让各类型的企业都 ...
- 云计算之路-阿里云上:Wireshark抓包分析一个耗时20秒的请求
这篇博文分享的是我们针对一个耗时20秒的请求,用Wireshark进行抓包分析的过程. 请求的流程是这样的:客户端浏览器 -> SLB(负载均衡) -> ECS(云服务器) -> S ...
- 用Wireshark抓包分析超过70秒的请求
超过70秒的请求是通过分析IIS日志发现的: 10.159.63.104是SLB的内网IP. 通过Wireshark抓包分析请求是9:22:21收到的(tcp.stream eq 23080): 09 ...
- 京东B2B业务架构演变
京东 B2B 业务的定位是让各类型的企业都可以在京东的 B 平台上进行采购.建立采购关系. 京东 B2B 的用户群体主要分为 2 类,一类是大 B 用户.另一类是小 B 用户.比如联通.移动公司跟京东 ...
- 大型电商业务架构 IT大咖说 - 大咖干货,不再错过
大型电商业务架构 IT大咖说 - 大咖干货,不再错过 http://www.itdks.com/dakashuo/new/dakalive/detail/591
随机推荐
- kuangbin专题 数论基础 part1?
线段树专题太难了,那我来做数学吧! 但数学太难了,我......(扯 这两天想了做了查了整理了几道数学. 除了一些进阶的知识,像莫比乌斯反演,杜教筛,min25学不会我跳了,一些基础的思维还是可以记录 ...
- OpenSSL 自述
1995 年, Eric A. Young 和 Tim J. Hudson 发明了 SSLeay,它是 SSL(Open-source Secure Sockets) 协议的实现.1998 年,You ...
- Microsemi Libero使用技巧——使用命令行模式下载程序
前言 在工程代码编译完成之后,如果需要给某个芯片下载程序时,或者是工厂量产烧录程序时,我们不需要把整个工程文件给别人,而只需要把生成的下载文件给别人,然后使用FlashPro就可以单独下载程序文件了. ...
- PDF提取表格的网页工具——Excalibur
在之前的文章另类爬虫:从PDF文件中爬取表格数据中,我们知道如何利用Python的camelot模块,通过写Python程序来提取PDF中的表格数据.本文我们将学习如何用更便捷的工具从PDF中提取 ...
- 精通awk系列(13):print、printf、sprintf和重定向
回到: Linux系列文章 Shell系列文章 Awk系列文章 输出操作 awk可以通过print.printf将数据输出到标准输出或重定向到文件. print print elem1,elem2,e ...
- 【2019的idea插件jreber使用】
前言 前面的idea安装说明已经可以完全使用了,没有安装的2019版idea的小伙伴可以去参考我上面的博客:https://www.cnblogs.com/liwangwang/p/11348434. ...
- Java基础语法04面向对象上-类-属性-方法-可变参数-重载-递归-对象数组
类 面向对象是一种思想,一般指将事务的属性与方法抽出总结为模板(类/class),处理事务时通过类创建/new出对象由对象的功能/方法去完成所要计算处理的事情. 面向过程:POP:以过程,步骤为主,考 ...
- Password Management:Password in Configuration File 密码管理:配置文件中的密码
- Angular--AOT和JIT两种编译方式带来的改变
Angular 应用主要由组件及其 HTML 模板组成.由于浏览器无法直接理解 Angular 所提供的组件和模板,因此 Angular 应用程序需要先进行编译才能在浏览器中运行.Angular 提供 ...
- centos_redis 安装脚本
#!/bin/bash # change to root echo "start to install build env..." sudo yum groupinstall &q ...