秒杀系统的设计思路

简介: 你好看官,里面请!今天笔者讲的是秒杀系统的设计思路。不懂或者觉得我写的有问题可以在评论区留言,我看到会及时回复。 注意:本文仅用于学习参考,不可用于商业用途,如需转载请跟我联系。

彻底搞定秒杀系统

如果觉得写的还可以,点个赞支持一下笔者呗!你的点赞和关注会让我更快更新哦。笔者会持续更新关于Java和大数据有关的文章。目前集中精力在更新java框架的内容。

1. 前言

如果你已经开始工作了,那么你在面试的时候一定被问过秒杀场景的问题。如果你还在上学,那么你以后在面试中肯定会遇到秒杀场景的问题。既然秒杀相关的问题无法回避,那么我们就正面刚一刚。

要搞定一个 “难题” 最重要的是什么?当然是要搞明白问题的核心或者说是本质。下面让我们一起揭开秒杀华丽的外表,一探它内在的本质。

首先,回忆一下那些电商平台的秒杀:xx 日 xx 时一块钱秒杀一部手机;xx 日 xx 时两块钱秒杀一部电脑等等。不管秒杀什么,其超低的价格都会引来大量用户抢购(这就是秒杀华丽外表下的真正目的,利用人性的贪婪,达到宣传推广的目的。哈哈,但这不是我们要讨论的重点)。所以,秒杀场景具有以下特点:

  1. 需求远大于资源
  2. 瞬间并发量极大

因此,我们需要解决两个问题:

  1. 防止超卖
  2. 抗住高并发

知己知彼,方能百战不殆。了解完秒杀,我们接下来分析一下我们自身。其实每个人都是天生的秒杀高手,不记得了?这也不能怪你,当时你年纪还太小,以至于你对那次激烈程度不亚于双十一的 “秒杀” 比赛忘得一干二净。当年是如此的英勇才跑赢其他兄弟姐妹,赢得了这场世纪大秒杀,然后来到了这个世界。这下想起来了吧(如果还没有,就去翻一下中学的生物课本吧,我救不了你了)。

2. 合格的秒杀系统

接下来我们看一下,作为一个合格的秒杀系统,我们需要解决哪些问题:

2.1 核心问题

高并发

高并发现象就像是写在秒杀的基因里一样,远低于正常情况下的价格,势必会让人趋之若鹜。这是人性所致,我们无法避免,只能正面解决。如果系统没有应对高并发的能力,那么系统挂掉,会带来无法估量的损失。所以应对高并发的能力是秒杀系统的头等大事,因为系统挂了,啥也没有了。

超卖

超卖问题同样非常严重,如果秒杀的是纸尿裤,超卖个几百条倒还顶得住。但如果是手机、电脑或者更贵的物品,超卖的后果很严重。要么直接把店卖了然后给用户发货,要么耍赖让有关部门查封你。不管怎样反正你的店是保不住了。

2.2 安全问题

恶意请求

在利益的驱使下,人的 “聪明才智” 会被激发出来。有人会用程序去刷你的秒杀接口,这样会导致真正的用户基本上没有秒杀成功的可能了,人的手速再快也赶不上机器,根本不是一个数量级。黄牛的力量不能小觑,这可是一个职业化的群体呀。专业的程序 + 顶级的硬件 + 顶级的带宽,就没有他们抢不到的东西(好像明白了为什么通过 12306 买不到票,而通过黄牛却能买到)。

提前秒杀

秒杀接口事先泄露,导致商品被提前秒杀。不对呀,我在程序中设置了时间限制,怎么可能有人能提前秒杀呢?很简单,假如我知道了秒杀的地址,那么我就可以写个程序不断的请求秒杀接口,秒杀时间一到,请求会马上成功。等真正人肉秒杀的用户反应过来秒杀已经开始的时候,商品早已经是我的囊中之物了。我只需要保证可以在所有用户前面将商品秒杀即可。

2.3 独善其身

作为一个秒杀系统,一定不能因为自己而影响了主业务。秒杀毕竟是用来带人气,为主业务拉流量的。不能因为秒杀系统出现故障导致主业务无法进行。这是作为一个秒杀系统最起码的职业操守。

3. 怎么做?

我们详细分析了秒杀系统所面临的问题,接下来我们就需要对症下药,将这些问题一一化解。

3.1 应对高并发

高并发下性能瓶颈主要来自两方面:

  1. WEB 服务
  2. 数据库

一个 WEB 容器节点的并发能力一般都在几百或几千的数量级,而一般秒杀活动的请求量都是十万级起步的。秒杀前商家都会进行大量宣传,各种营销渠道一通狂轰乱炸之后,前来捡便宜的人一定不少。甚至有些秒杀活动,根本就不需要任何宣传,都会有大量的用户一窝蜂地涌进来 —— 比如春运期间的 12306。各种抢票软件,专业抢票天团(黄牛),再加上 12306 本身的流量,高峰期达到千万级也是很轻松的。这也是直接导致前些年 12306 屡屡瘫痪的一个重要原因。

不过好在 WEB 服务扩展起来相对容易,就像孙悟空一样拔几根猴毛一吹,变出一群分身。在云服务如此完善的时代,临时增加服务节点变得异常简单。扩展出足够多的秒杀系统集群,再使用 NGINX 做负载均衡,可以搞定 WEB 服务并发的问题。

至于数据库方面,就需要我们的 Redis 出场啦。Cluster + 主从同步 + 读写分离可以解数据库之忧。这些工作做完以后,还可以进一步优化,将页面静态化,并将静态资源尽量一一放到 CDN 上缓存起来,进一步减少对服务器的请求。

3.2 解决超卖

解决超卖问题有多种方案,可以利用 Redis 的 decr 命令的原子性来做减库存操作。也可以使用分布式锁(我们前面已经学过了)来保证减库存操作的原子性。还可以单线程队列来解决。

decr 命令是对 key 值进行减一的操作,它具有原子性,执行 decr 返回减一后的值,那么我们就可以这样来判断:if (decr (productId)<0) 如果条件成立,那么就代表商品售罄,秒杀失败。而关于分布式锁的方式,可以翻阅之前的小节内容。单线程队列就更不用说了,都单线程了,超卖的问题肯定就不存在了。

3.3 消除安全隐患

上面我们提到了恶意请求和提前秒杀的问题,无非就是因为秒杀地址被提前泄露。要解决这个问题并不难。写一个简单的随机方法,将秒杀请求的地址动态化,即使系统的开发者也无法事先预知真正的秒杀地址是什么。

3.4 消除对现有业务的影响

解决方案也很简单,就是不要把秒杀系统和现有业务系统放到同一个 “篮子里”。将秒杀系统单独部署,从前端、后端、缓存、数据库,统统独立部署。这样就算秒杀系统再怎么崩溃、瘫痪,也绝对不会对现有系统造成影响。

3.5 再加固

按照上面的方案,应对一般的秒杀已经没问题了。如果你还不放心,可以继续加固 —— 限流、削峰保驾护航。限流可以挡住不能承受的那部分流量,就像早高峰地铁站的限流一样,地铁的运输能力就那么大,发车频率也已经到了极限,如果不限流,把乘客都放进站,分分钟给你填满整个候车室。而削峰有点像我们错峰上班,互联网公司一般都十点上班,为的就是错开八九点的早高峰。程序中通常采用消息队列(MQ)来达到削峰的目的。

4. 总结一下

OK,上面说了很多,接下来我们整理一下思路,先看图:

网络异常,图片无法展示
|

  1. 静态化 + CDN,减少服务器负担
  2. NGINX + 服务集群,提升处理能力
  3. Redis 缓冲,消除数据库压力
  4. MySQL 持久化,保证数据的可靠与稳定

图中体现了大的框架,我们还可以加入定时任务来做缓存预热和数据同步。使用 MQ 做订单后处理等。秒杀最重要的是做好架构层面的设计,真正的编码实现与其他业务并没有太多不同。

相关文章
|
7月前
|
消息中间件 NoSQL Redis
秒杀的设计思路与实践
秒杀的设计思路与实践
65 1
|
2月前
|
缓存 前端开发 NoSQL
如何设计一个秒杀系统?
本文详细介绍了秒杀系统的原理与设计方法,包括高性能、一致性、高可用性和可扩展性等方面的要求。文中通过前端和后端的设计方案,探讨了如何实现秒杀系统的高并发处理,例如页面静态化、限流、降级策略及缓存优化等。此外,还分享了实际项目中的库存系统架构设计经验,并提供了面试中如何回答此类问题的建议。
197 2
|
2月前
|
缓存 NoSQL 应用服务中间件
【开发系列】秒杀系统的设计
【开发系列】秒杀系统的设计
|
缓存 NoSQL 数据库
【高并发】秒杀系统设计思路
【高并发】秒杀系统设计思路
216 0
|
7月前
|
缓存 前端开发 安全
秒杀系统架构分析与实战
秒杀系统架构分析与实战
202 1
|
消息中间件 缓存 NoSQL
如何设计一个秒杀系统???
如何设计一个秒杀系统???
188 0
|
消息中间件 缓存 安全
秒杀系统(1)——秒杀功能设计理念
秒杀系统(1)——秒杀功能设计理念
186 0
|
消息中间件 缓存 JavaScript
如何设计一个秒杀系统
如何设计一个秒杀系统
|
消息中间件 负载均衡 应用服务中间件
秒杀场景的设计思路和方案
秒杀场景的设计思路和方案
373 0
|
数据采集 域名解析 缓存
设计一个秒杀系统架构
对于秒杀架构的设计,需要遵循以下个原则: 东西不能超卖、 下单成功的订单数据不能丢失、 服务器和数据库不能挂 尽量不让机器人抢走 整体的思路 秒杀架构的设计方案就是一个不断过滤请求的过程,从系统架构层面来说,秒杀系统的分层思路如下。
179 0