秒杀系统的设计思路

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

彻底搞定秒杀系统

如果觉得写的还可以,点个赞支持一下笔者呗!你的点赞和关注会让我更快更新哦。笔者会持续更新关于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 做订单后处理等。秒杀最重要的是做好架构层面的设计,真正的编码实现与其他业务并没有太多不同。

相关文章
|
29天前
|
消息中间件 NoSQL Redis
秒杀的设计思路与实践
秒杀的设计思路与实践
23 1
|
29天前
|
缓存 前端开发 安全
秒杀系统架构分析与实战
秒杀系统架构分析与实战
66 0
|
8月前
|
缓存 NoSQL 数据库
【高并发】秒杀系统设计思路
【高并发】秒杀系统设计思路
127 0
|
6月前
|
消息中间件 缓存 安全
秒杀系统(1)——秒杀功能设计理念
秒杀系统(1)——秒杀功能设计理念
102 0
|
7月前
|
消息中间件 缓存 JavaScript
如何设计一个秒杀系统
如何设计一个秒杀系统
|
7月前
|
消息中间件 负载均衡 应用服务中间件
秒杀场景的设计思路和方案
秒杀场景的设计思路和方案
82 0
|
8月前
|
消息中间件 缓存 负载均衡
秒杀系统设计:高并发下的架构考虑
随着互联网的快速发展,电商平台上的秒杀活动越来越受欢迎。然而,高并发的情况下,如何保证秒杀系统的稳定性和可扩展性成为一个非常具有挑战性的问题。在本文中,我们将讨论如何设计一个高效、可靠的秒杀系统。
140 1
|
消息中间件 缓存 NoSQL
如何设计一个秒杀系统???
如何设计一个秒杀系统???
154 0
|
数据采集 域名解析 缓存
设计一个秒杀系统架构
对于秒杀架构的设计,需要遵循以下个原则: 东西不能超卖、 下单成功的订单数据不能丢失、 服务器和数据库不能挂 尽量不让机器人抢走 整体的思路 秒杀架构的设计方案就是一个不断过滤请求的过程,从系统架构层面来说,秒杀系统的分层思路如下。
130 0
|
缓存 NoSQL 前端开发
秒杀系统设计的5个要点
比如有10件商品要秒杀,可以放到缓存中,读写时不要加锁。 当并发量大的时候,可能有25个人秒杀成功,这样后面的就可以直接抛秒杀结束的静态页面。进去的25个人中有15个人是不可能获得商品的。所以可以根据进入的先后顺序只能前10个人购买成功。后面15个人就抛商品已秒杀完。
282 0