电商网站秒杀和抢购的高并发技术实现和优化

author author     2022-12-07     635

关键词:

一、如何防止多个用户同时抢购同一商品,防止高并发同时订购同一商品?

最近双十一抢购系统应用频繁,销量火爆的同时,让人头疼是却是多用户高并发情况下出现的库存问题。

据调查,多个用户同时下单,导致查询和插入不同步,而查询和插入有时间差,导致高并发情况下的库存问题(我的项目大概就是这种情况。首先,for update找出商品信息表,并将其放入全局表-表数组中。当用户扣除余额成功后,更新商品信息表,减去用户订单的数量。数据库使用Mysql,查询商品信息表时被锁定。但是当商品信息表中的数据越来越多时,查询就存在时间差,导致高并发。商品信息表放入变量数组时,执行后的时间差内其他用户也在下单,导致库存问题)。

现在问一个问题。如何防止同一产品同时被多个用户抢购。也就是说,同一秒内只能有一个用户下单。那下面就说说我们实现CRMEB Pro版高并发高性能时的开发思路:首先想到的思路是排队,阻塞队列。

1、update table set num=num-1 where num>1不查直接更新,更新成功代表抢到了

2、把抢购系统分为两步,第一步是下单(即抢购),如果订单成功,立即减少数量并更新表格数据。第二步,付款。在后台写一个程序。半小时不付款,自动删除订单,然后增加数量。这样就可以避免并发。如果一步完成,那么短时间内也会出现并发问题。

3、数据库中可以加行锁

4、可以使用队列+锁表来解决

二、Web系统大规模并发 - 秒杀和抢购的技术实现和优化

电商的秒杀和抢购对我们来说并不是一件陌生的事情。但是,从技术的角度来看,这对Web系统是一个极大的考验。当一个Web系统在一秒钟内收到上万甚至更多的请求时,系统的优化和稳定性就显得非常重要。这次将关注秒杀和抢购的技术实现和优化。同时从技术层面揭开我们总是很难抢到火车票的原因。 ​

1.大规模并发带来的挑战

在过去的工作中,我曾经面对过每秒5w的高并发秒杀项目。在这个过程中,整个Web系统遇到了很多问题和挑战。Web系统如果不优化,很容易陷入异常状态。现在我们来讨论一下优化的思路和方法。

(1)请求接口的合理设计

一个秒杀或者抢购页面,通常分为2个部分,一个是静态的HTML等内容,另一个就是参与秒杀的Web后台请求接口。

通常通过CDN部署静态HTML等内容,所以压力普遍较低,核心瓶颈其实在后台请求接口上。这个后端接口必须能够支持高并发请求。同时,在最短的时间内尽快返回用户的请求结果也是非常重要的。为了尽快实现这一点,接口的后端存储将使用内存级操作。此时,如果继续指向MySQL之类的存储就不太合适,如果有这样复杂的业务需求,推荐异步写入。

电商网站秒杀和抢购的高并发技术实现和优化​_商城系统


图片来自网络,侵权联系删除

当然,也有一些秒杀和抢购采用“滞后反馈”,也就是说,你此刻并不知道秒杀的结果,过一段时间你才能从页面上看到用户是否秒杀成功。但这种“偷懒”的行为,同时给用户的体验也不好,容易被用户认为是“暗箱操作”。​

(2)高并发的挑战:一定要“快”

我们通常用QPS(每秒请求数)来衡量一个Web系统的吞吐率,这对于解决每秒上万次的高并发场景至关重要。例如,我们假设处理一个业务请求的平均响应时间是100毫秒。同时系统中有20台Apache Web服务器,配置MaxClients为500个(表示Apache的最大连接数)。

那么,我们的Web系统的理论峰值QPS为(理想化的计算方式):

20*500/0.1 = 100000 (10万QPS)

这么一看我们的系统好像很强大,一秒钟可以处理10万个请求,5w/s的秒杀好像是“纸老虎”。实际情况当然不是那么理想。在实际的高并发场景中,机器处于高负载状态,此时平均响应时间会大大增加。

就Web服务器而言,Apache打开的连接进程越多,CPU需要处理的上下文切换就越多,增加了CPU消耗,进而直接导致平均响应时间的增加。所以上面说的MaxClient的数量要根据CPU、内存等硬件因素综合考虑,绝对不是越多越好。你可以用Apache自己的abench测试一下,取一个合适的值。然后,我们选择内存操作级别存储的Redis。在高并发状态下,存储的响应时间至关重要。虽然网络带宽也是一个因素,但是,这种请求包通常很小,很少成为请求的瓶颈。负载均衡成为系统瓶颈的情况很少,这里就不讨论了。

那么问题来了,假设我们的系统,在5w/s的高并发状态下,平均响应时间从100ms变为250ms(实际情况,甚至更多):

20*500/0.25 = 40000 (4万QPS)

于是,我们的系统剩下了4w的QPS,面对5w每秒的请求,中间相差了1w。

然后,这才是真正的恶梦开始。举个例子,高速路口,1秒钟来5部车,每秒通过5部车,高速路口运作正常。突然,这个路口1秒钟只能通过4部车,车流量仍然依旧,结果必定出现大塞车。(5条车道忽然变成4条车道的感觉)

同理,某一个秒内,20*500个可用连接进程都在满负荷工作中,却仍然有1万个新来请求,没有连接进程可用,系统陷入到异常状态也是预期之内。

电商网站秒杀和抢购的高并发技术实现和优化​_电商零售_02


图片来自网络,侵权联系删除

其实在正常的非高并发的业务场景中,也有类似的情况出现,某个业务请求接口出现问题,响应时间极慢,将整个Web请求响应时间拉得很长,逐渐将Web服务器的可用连接数占满,其他正常的业务请求,无连接进程可用。

更可怕的问题是,是用户的行为特点,系统越是不可用,用户的点击越频繁,恶性循环最终导致“雪崩”(其中一台Web机器挂了,导致流量分散到其他正常工作的机器上,再导致正常的机器也挂,然后恶性循环),将整个Web系统拖垮。

(3)重启与过载保护

如果系统发生“雪崩”,贸然重启服务,是无法解决问题的。最常见的现象是,启动起来后,立刻挂掉。这个时候,最好在入口层将流量拒绝,然后再将重启。如果是redis/memcache这种服务也挂了,重启的时候需要注意“预热”,并且很可能需要比较长的时间。

秒杀和抢购的场景,流量往往是超乎我们系统的准备和想象的。这个时候,过载保护是必要的。如果检测到系统满负载状态,拒绝请求也是一种保护措施。在前端设置过滤是最简单的方式,但是,这种做法是被用户“千夫所指”的行为。更合适一点的是,将过载保护设置在CGI入口层,快速将客户的直接请求返回。

2.作弊的手段:进攻与防守

秒杀和抢购收到了“海量”的请求,实际上里面的水分是很大的。不少用户,为了“抢“到商品,会使用“刷票工具”等类型的辅助工具,帮助他们发送尽可能多的请求到服务器。还有一部分高级用户,制作强大的自动请求脚本。这种做法的理由也很简单,就是在参与秒杀和抢购的请求中,自己的请求数目占比越多,成功的概率越高。

这些都是属于“作弊的手段”,不过,有“进攻”就有“防守”,这是一场没有硝烟的战斗哈。

(1)同一个账号,一次性发出多个请求

部分用户通过浏览器的插件或者其他工具,在秒杀开始的时间里,以自己的账号,一次发送上百甚至更多的请求。实际上,这样的用户破坏了秒杀和抢购的公平性。

这种请求在某些没有做数据安全处理的系统里,也可能造成另外一种破坏,导致某些判断条件被绕过。例如一个简单的领取逻辑,先判断用户是否有参与记录,如果没有则领取成功,最后写入到参与记录中。这是个非常简单的逻辑,但是,在高并发的场景下,存在深深的漏洞。多个并发请求通过负载均衡服务器,分配到内网的多台Web服务器,它们首先向存储发送查询请求,然后,在某个请求成功写入参与记录的时间差内,其他的请求获取查询到的结果都是“没有参与记录”。这里,就存在逻辑判断被绕过的风险。

电商网站秒杀和抢购的高并发技术实现和优化​_电商零售_03


图片来自网络,侵权联系删除

应对方案:

在程序入口处,一个账号只允许接受1个请求,其他请求过滤。不仅解决了同一个账号,发送N个请求的问题,还保证了后续的逻辑流程的安全。实现方案,可以通过Redis这种内存缓存服务,写入一个标志位(只允许1个请求写成功,结合watch的乐观锁的特性),成功写入的则可以继续参加。

电商网站秒杀和抢购的高并发技术实现和优化​_高并发_04

图片来自网络,侵权联系删除

或者,自己实现一个服务,将同一个账号的请求放入一个队列中,处理完一个,再处理下一个。​

(2)多个账号,一次性发送多个请求

很多公司的账号注册功能,在发展早期几乎是没有限制的,很容易就可以注册很多个账号。因此,也导致出现了一些特殊的工作室,通过编写自动注册脚本,积累了一大批“僵尸账号”,数量庞大,几万甚至几十万的账号不等,专门做各种刷的行为(这就是微博中的“僵尸粉“的来源)。举个例子,例如微博中有转发抽奖的活动,如果我们使用几万个“僵尸号”去混进去转发,这样就可以大大提升我们中奖的概率。

这种账号,使用在秒杀和抢购里,也是同一个道理。例如,iPhone官网的抢购,火车票黄牛党。

电商网站秒杀和抢购的高并发技术实现和优化​_商城系统_05


图片来自网络,侵权联系删除

应对方案:

这种场景,可以通过检测指定机器IP请求频率就可以解决,如果发现某个IP请求频率很高,可以给它弹出一个验证码或者直接禁止它的请求:


(3)弹出验证码

最核心的追求,就是分辨出真实用户。因此,大家可能经常发现,网站弹出的验证码,有些是“鬼神乱舞”的样子,有时让我们根本无法看清。他们这样做的原因,其实也是为了让验证码的图片不被轻易识别,因为强大的“自动脚本”可以通过图片识别里面的字符,然后让脚本自动填写验证码。实际上,有一些非常创新的验证码,效果会比较好,例如给你一个简单问题让你回答,或者让你完成某些简单操作(例如百度贴吧的验证码)。

(4)直接禁止IP

实际上是有些粗暴的,因为有些真实用户的网络场景恰好是同一出口IP的,可能会有“误伤“。但是这一个做法简单高效,根据实际场景使用可以获得很好的效果。​

(5)多个账号,不同IP发送不同请求

所谓道高一尺,魔高一丈。有进攻,就会有防守,永不休止。这些“工作室”,发现你对单机IP请求频率有控制之后,他们也针对这种场景,想出了他们的“新进攻方案”,就是不断改变IP。​

电商网站秒杀和抢购的高并发技术实现和优化​_高并发_06


图片来自网络,侵权联系删除

有同学会好奇,这些随机IP服务怎么来的。有一些是某些机构自己占据一批独立IP,然后做成一个随机代理IP的服务,有偿提供给这些“工作室”使用。还有一些更为黑暗一点的,就是通过木马黑掉普通用户的电脑,这个木马也不破坏用户电脑的正常运作,只做一件事情,就是转发IP包,普通用户的电脑被变成了IP代理出口。通过这种做法,黑客就拿到了大量的独立IP,然后搭建为随机IP服务,就是为了挣钱。

应对方案:

说实话,这种场景下的请求,和真实用户的行为,已经基本相同了,想做分辨很困难。再做进一步的限制很容易“误伤“真实用户,这个时候,通常只能通过设置业务高门槛来限制这种请求了,或者通过账号行为的”数据挖掘“来提前清理掉它们。

僵尸账号也还是有一些共同特征的,例如账号很可能属于同一个号码段甚至是连号的,活跃度不高,等级低,资料不全等等。根据这些特点,适当设置参与门槛,例如限制参与秒杀的账号等级。通过这些业务手段,也是可以过滤掉一些僵尸号。

(6)火车票的抢购

看到这里,同学们是否明白你为什么抢不到火车票?如果你只是老老实实地去抢票,真的很难。通过多账号的方式,火车票的黄牛将很多车票的名额占据,部分强大的黄牛,在处理验证码方面,更是“技高一筹“。

高级的黄牛刷票时,在识别验证码的时候使用真实的人,中间搭建一个展示验证码图片的中转软件服务,真人浏览图片并填写下真实验证码,返回给中转软件。对于这种方式,验证码的保护限制作用被废除了,目前也没有很好的解决方案。

电商网站秒杀和抢购的高并发技术实现和优化​_高性能_07


图片来自网络,侵权联系删除

因为火车票是根据身份证实名制的,这里还有一个火车票的转让操作方式。大致的操作方式,是先用买家的身份证开启一个抢票工具,持续发送请求,黄牛账号选择退票,然后黄牛买家成功通过自己的身份证购票成功。当一列车厢没有票了的时候,是没有很多人盯着看的,况且黄牛们的抢票工具也很强大,即使让我们看见有退票,我们也不一定能抢得过他们哈。​

电商网站秒杀和抢购的高并发技术实现和优化​_高性能_08

图片来自网络,侵权联系删除

最终,黄牛顺利将火车票转移到买家的身份证下。

这种情况并没有很好的解决方案,唯一可以动心思的也许是对账号数据进行“数据挖掘”,这些黄牛账号也是有一些共同特征的,例如经常抢票和退票,节假日异常活跃等等。将它们分析出来,再做进一步处理和甄别。​

3.高并发下的数据安全

我们知道在多线程写入同一个文件的时候,会存现“线程安全”的问题(多个线程同时运行同一段代码,如果每次运行结果和单线程运行的结果是一样的,结果和预期相同,就是线程安全的)。如果是MySQL数据库,可以使用它自带的锁机制很好的解决问题,但是,在大规模并发的场景中,是不推荐使用MySQL的。

秒杀和抢购的场景中,还有另外一个问题,就是“超库存”,如果在这方面控制不慎,会产生发送过多的情况。我们也曾经听说过,某些电商搞抢购活动,买家成功拍下后,商家却不承认订单有效,拒绝发货。这里的问题,也许并不一定是商家奸诈,而是系统技术层面存在超发风险导致的。

(1)超过库存的原因假设在一个购买场景中,我们总共只有100件商品。最后时刻,我们已经消耗了99件物品,只剩下最后一件。此时系统发送了多个并发请求,都是读取99个产品剩余,然后都通过了这个剩余判断,最终导致单量超过库存。(与文章前面提到的场景相同)

电商网站秒杀和抢购的高并发技术实现和优化​_高性能_09

图片来自网络,侵权联系删除

在上面的这个图中,就导致了并发用户B也“抢购成功”,多让一个人获得了商品。这种场景,在高并发的情况下非常容易出现。

(2)悲观锁思路解决线程安全的思路很多,可以从“悲观锁”的方向开始讨论。
悲观锁,也就是在修改数据的时候,采用锁定状态,排斥外部请求的修改。遇到加锁的状态,就必须等待。

电商网站秒杀和抢购的高并发技术实现和优化​_高性能_10


图片来自网络,侵权联系删除

虽然上面的方案确实解决了线程安全的问题,但是别忘了我们的场景是“高并发”。也就是说,会有很多这样的修改请求,每一个都需要等待“锁”。一些线程可能永远也不会有机会获得这个“锁”,这样的请求会死在那里。同时会有很多这样的请求,会瞬间增加系统的平均响应时间。结果可用连接的数量将被耗尽,系统将陷入异常。

(3)FIFO队列思路让我们稍微修改一下上面的场景。我们直接将请求放入队列中,采用FIFO(先入先出)。这样,我们就不会导致一些请求永远获取不到锁。看到这里,是不是有点把多线程强行变成单线程的感觉?

电商网站秒杀和抢购的高并发技术实现和优化​_高性能_11

图片来自网络,侵权联系删除

然后,我们现在解决了锁的问题,所有请求都在“先进先出”队列中处理。那么新的问题来了。在高并发的场景下,队列内存很可能因为请求多而瞬间“爆仓”,然后系统会再次陷入异常状态。或者设计一个巨大的内存队列也是一个解决方案。但是,系统能够完成一个队列中请求的速度,是无法和疯狂涌入队列的数量相比的。也就是说,队列中的请求会越积越多,最后Web系统的平均响应时间会急剧下降,系统仍然会陷入异常。

(4)乐观锁思路

这时候就可以讨论“乐观锁定”的思路了。乐观锁采用比“悲观锁”更宽松的锁机制,大部分都是用版本号更新的。也就是说,该数据的所有请求都有资格被修改,但是将获得该数据的版本号。只有版本号符合的才能更新成功,其他的都返回失败。这样我们就不需要考虑队列问题,不过会增加CPU的计算开销。但总的来说,这是一个更好的解决方案。

电商网站秒杀和抢购的高并发技术实现和优化​_高并发_12

图片来自网络,侵权联系删除

有很多软件和服务都有“乐观锁”功能的支持,例如Redis中的watch就是其中之一。通过这个实现,我们保证了数据的安全。

总结:

本文讨论了商城项目高并发服务在面对大流量时的一些技术手段和应对要点。当然,实际的在线服务要比现在的复杂。这里只是一些建议。希望能保持敬畏之心,在高并发的道路上继续探索。做出更好的互联网商城应用。


web系统大规模并发——电商秒杀与抢购

电商的秒杀和抢购,对我们来说,都不是一个陌生的东西。然而,从技术的角度来说,这对于Web系统是一个巨大的考验。当一个Web系统,在一秒钟内收到数以万计甚至更多请求时,系统的优化和稳定至关重要。这次我们会关注秒... 查看详情

web系统大规模并发——电商秒杀与抢购

电商的秒杀和抢购,对我们来说,都不是一个陌生的东西。然而,从技术的角度来说,这对于Web系统是一个巨大的考验。当一个Web系统,在一秒钟内收到数以万计甚至更多请求时,系统的优化和稳定至关重要。这次我们会关注秒... 查看详情

电商网站秒杀与抢购的系统架构

一、大规模并发带来的挑战在过去的工作中,我曾经面对过5w每秒的高并发秒杀功能,在这个过程中,整个Web系统遇到了很多的问题和挑战。如果Web系统不做针对性的优化,会轻而易举地陷入到异常状态。我们现在一起来讨论下... 查看详情

test

互联网特别是电商平台,阿里双11秒杀、还有12306春运抢票、以及平时各种节假日抢购活动等,都是典型的高并发场景。这类场景最大的特征就是活动周期短,瞬间流量大(高并发),大量的人短期涌入服务器抢购,但是数量有... 查看详情

redis轻松实现秒杀系统(代码片段)

...xff0c;实用技术文章及时了解什么是秒杀秒杀场景一般会在电商网站举行一些活动或者节假日在12306网站上抢票时遇到。对于电商网站中一些稀缺或者特价商品,电商网站一般会在约定时间点对其进行限量销售,因为这些商... 查看详情

redis轻松实现秒杀系统(代码片段)

...xff0c;实用技术文章及时了解什么是秒杀秒杀场景一般会在电商网站举行一些活动或者节假日在12306网站上抢票时遇到。对于电商网站中一些稀缺或者特价商品,电商网站一般会在约定时间点对其进行限量销售,因为这些商... 查看详情

关于秒杀与抢购

...---------------------------------------------------------------------------电商的秒杀和抢购,对我们来说,都不是一个陌生的东 查看详情

网站抢购秒杀系统设计简析

秒杀是电子商务网站常见的一种营销手段。原则不要整个系统宕机。即使系统故障,也不要将错误数据展示出来。尽量保持公平公正。实现效果秒杀开始前,抢购按钮为活动未开始。秒杀开始时,抢购按钮可以点击下单。秒杀结... 查看详情

一个基于ssm框架开发的高并发电商秒杀web系统(代码片段)

0前言一个基于SSM框架的高并发秒杀系统采用IDEA+Maven+SSM+Mysql+Redis+Jetty、Bootstrap/Jquery开发。通过这个小项目,理清了基于SSM框架开发Web应用的流程以及常见的避坑方法,并在最后简单采用了Redis缓存以及MysqlProcedure对项目进行了高... 查看详情

秒杀系统架构分析与实战--转载

...互联网服务的用户越多,高并发的场景也变得越来越多。电商秒杀和抢购,是两个比较典型的互联网高并发场景。虽然我们解决问题的具体技术方案可能千差万别,但是遇到的挑战却是相似的,因此解决问题的思路也异曲同工。... 查看详情

秒杀/抢购系统设计优化

...览器页面以保证不会错过秒杀,这些请求如果按照一般的网站应用架构,访问应用服务器、连接数据库,会对应用服务器和数据库服务器造成负载压力 查看详情

电商 秒杀系统 设计思路和实现方法(代码片段)

电商 秒杀系统 设计思路和实现方法2017年05月26日00:06:35阅读数:36621秒杀业务分析正常电子商务流程(1)查询商品;(2)创建订单;(3)扣减库存;(4)更新订单;(5)付款;(6)卖家发货秒杀业务的特性(1)低廉价格... 查看详情

秒杀的设计思路

电商:如何设计一个秒杀系统  什么是秒杀秒杀场景一般会在电商网站举行一些活动或者节假日在12306网站上抢票时遇到。对于电商网站中一些稀缺或者特价商品,电商网站一般会在约定时间点对其进行限量销售,因为这... 查看详情

大规模并发带来的挑战

...:在过去的工作中,我曾经面对过5w每秒的高并发秒杀功能,在这个过程中,整个Web系统遇到了很多的问题和挑战。如果Web系统不做针对性的优化,会轻而易举地陷入到异常状态。我们现在一起来讨论下,... 查看详情

电商秒杀系统设计思路和实现方法(代码片段)

1秒杀业务分析正常电子商务流程(1)查询商品;(2)创建订单;(3)扣减库存;(4)更新订单;(5)付款;(6)卖家发货秒杀业务的特性(1)低廉价... 查看详情

秒杀系统实现高并发的优化(代码片段)

...存储和更新结果和理想的设计不一致。用户角度??尼玛,网站这么卡,刷新了还这样,垃圾网站,不玩了四:阻碍服务速度的 查看详情

如何设计一个秒杀系统

什么是秒杀秒杀场景一般会在电商网站举行一些活动或者节假日在12306网站上抢票时遇到。对于电商网站中一些稀缺或者特价商品,电商网站一般会在约定时间点对其进行限量销售,因为这些商品的特殊性,会吸引大量用户前来... 查看详情

秒杀抢购系统优化思路详解

前几年,火车票购票网站12306,每到放假高峰期,在线票刷不出来,购买困难,甚至出现了各种插件支持抢票,这样的场景,对于每个买过票的人,应该印象深刻。小米手机的抢购活动,同样异常火爆,在几分钟的时间内,卖出... 查看详情