文档章节

实战讲解高并发和秒杀抢购系统设计

x
 xtof
发布于 09/22 15:34
字数 2272
阅读 5
收藏 0

互联网特别是电商平台,阿里双11秒杀、还有12306春运抢票、以及平时各种节假日抢购活动等,都是典型的高并发场景。

这类场景最大的特征就是活动周期短,瞬间流量大(高并发),大量的人短期涌入服务器抢购,但是数量有限,最终只有少数人能成功下单。

这里,就来讲一讲对应该场景下需要考虑的技术实现。

先从基本的概念的建立,再讲对应的实现部分。

第一:高并发

技术要做的事,一方面优化程序,让程序性能最优,单次请求时间能从50ms优化到25ms,那就可以在一秒钟内成功响应翻倍的请求了。

另一方面就是增加服务器,用更大的集群来处理用户请求,设计好一个可靠且灵活扩充的分布式方案就更加重要了。

第二:时间短

火热的秒杀活动,真的是一秒钟以内就会把商品抢购一空,而大部分用户的感受是,提交订单的过程却要等待好几秒、甚至十几秒,更糟糕的当然是请求报错。

那么一个好的秒杀体验,当然希望尽可能减少用户等待时间,准确的提示用户当前是否还有商品库存。而这些,也是需要有优秀的程序设计来保证的。

第三:系统容量预估

系统设计的时候,都需要有一个容量预估,那就是要提前计算好,我们设计的系统,要承载多大的数量级。

假如线上前端服务器规格是8核16G内存的服务器,而提交订单的处理程序耗时100ms,那么可以简单计算一下:

每秒可以处理的订单请求数=1000ms/100ms*8=80qps

上面这个结果,对于秒杀系统来说,肯定是非常不理想的。

如果能将处理程序耗时优化后,降低到10ms,那么就可以达到800qps。

如果我们可以把程序继续优化,能快速区分开有库存和无库存处理,那么无库存时处理就有可能做到1ms甚至更低的耗时。这样无库存时就能有更好的性能,上万的qps也是可以达到的。

上面的预估,都是针对单机,那么简单的增加前端服务器,是不是就能有更好的并发处理量呢?

肯定没这么简单,因为数据库、缓存系统甚至机房网络带宽都会成为瓶颈。

于是就要有一个更好的分布式方案。

第四:好的分布式方案

一个好的分布式方案,首先当然是稳定可靠,不要出乱子,然后就是方便扩充,最好的效果当然是增加一台服务器,并发处理量可以1:1线性增长。

比如:单机qps是1k,那么10台服务器可以做到1w,100台可以做到10w每秒。

要做到这样的线性增长效果,就要杜绝出现瓶颈,否则还是会代价太大。

拒绝假的分布式尤其重要,比如:前端服务器是可以独立存在的,但是都依赖集中的一个数据库或者缓存系统,那最后,一定是集中的那个数据库或者缓存系统受不了,同样无法做到一个好的分布式。

第五:关注系统的瓶颈

大家先有几个基本的共识,系统的处理速度

程序内数据读写 > redis > mysql > 磁盘

单机网络请求 > 局域网内请求 > 跨机房请求

我们优化程序的时候,尽量用最快的方式,尽量用最简短的逻辑。

用redis替代mysql来保存订单处理中依赖的数据,用程序中的提交的数据代替从redis中二次获取数据,比如:商品库存信息,用户订单信息。

逻辑处理中,把速度快且提前中断的逻辑放在最前面,比如:验证登录,验证问答。

我们做分布式方案的时候,尽量把资源调用放在最近的地方。

前端服务器依赖的数据尽量就在局域网内,如果能在单机都有读的redis服务当然更好,程序维护数据响应会复杂些。

不要出现跨机房网络请求,不要出现跨机房网络请求,不要出现跨机房网络请求,重要的事情说三遍。

第六:什么语言更适合这类系统

当然,像是用golang, ngx_lua可能在高并发和性能方面会更有优势。

如果使用java、php当然也是可以的,作为一个系统,语言只是工具,更好的设计和优化,才能达到最终想要的效果。

有了上面的基本概念,我们接下来再来看看,具体运行时,会出现什么状况。

下面是一些具体的实现问题:

问题1:库存超卖

只有10个库存,但是一秒钟有1k个订单,怎么能不超卖呢?

核心思想就是保证库存递减是原子性操作,10--返回9,9--返回8,8--返回7。

而不能是读取出来库存10,10-1=9再更新回去。因为这个读取和更新是并发执行的,很可能就会有1k个订单都成功了,而库存实际只有10。

那么,怎么保证原子性操作呢?

1 数据库:

update product set left_num=left_num-1 where left_num>0;

这里用到的是left_num=left_num-1,如果left_num>0才能执行成功,数据库查询、更新的时候有用到锁,是可以保证更新操作的原子性的。

数据库性能较差,不建议使用。

2 分布式锁

用redis来做一个分布式锁,reids->setnx('lock', 1) 设置一个锁,程序执行完成再del这个锁。

锁定的过程,不利于并发执行,大家都在等待锁解开,不建议使用。

3 消息队列

将订单请求全部放入消息队列,然后另外一个后台程序一个个处理队列中的订单请求。

并发不受影响,但是用户等待的时间较长,进入队列的订单也会很多,体验上并不好,也不建议使用。

4 redis递减

通过 redis->incrby('product', -1) 得到递减之后的库存数。

问题2:集群怎么来规划

前端服务器因为没有相互间关联,集群的数量不受影响。

redis的性能可以达到每秒几万次响应,所以一个集群的规模,也就是redis服务可以承载的数量。

比如:一台前端服务器是1~2k的qps(有库存时),那么10台+1台redis就可以是一个独立的集群,可以支撑1~2w每秒订单量。

10个上述的集群就可以做到一秒钟处理10w~20w的有效订单。

如果秒杀活动的库存量在1w以内,预计参与的人数在百万左右,那么有一个集群也就可以搞定。

如果秒杀参与的人数超过千万,那么就要用到不止一个集群了。

问题3:多个集群的数据怎么保持一致性

不要做多集群的数据同步,而是用散列,每个集群的数据是独立存在的。

假设,有10个商品,每个商品有1w库存,规划用10个集群,那么每个集群有10个商品,每个商品是1k库存。

每个集群只需要负责把自己的库存卖掉即可,至于说,会不会有用户知道有10个集群,然后每个集群都去抢。

这种情况就不要用程序来处理了,利用运营规则,活动结束后汇总订单的时候再去处理就好了。

如果担心散列的不合理,比如:某个集群用户访问量特别少,那么可以引入一个中控服务,来监控各个集群的库存,然后再做平衡。

问题4:机器人抢购怎么办:

没什么太好的办法,类似DDOS攻击,只能是让自身更强大才是王道。

运营策略上,可以严格控制用户注册,必须登录,提交订单的时候引入图像验证码,问答,交互式验证等。

本文转载自:https://www.jianshu.com/p/9a35105ea328?utm_campaign=studygolang.com&utm_medium=studygolang.com&ut...

共有 人打赏支持
x
粉丝 0
博文 76
码字总数 78944
作品 0
深圳
秒杀系统企业级实战应用(真实工业界案例)

随着互联网不断发展,电商越来越流行,商家为了多卖商品,给宝贝们标出了放血的价格, 剁手党们也是参与各种抢购和秒杀活动。那么问题来了,面对瞬间爆发的访问压力和海量的交易数据,我们该...

小红牛
05/17
0
0
热点推荐:秒杀系统架构分析与实战

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

洋哥6
2016/04/14
359
1
PHP秒杀系统 高并发高性能的极致挑战

先说一下体会,这个老师讲的算是比较慢的了,而且语义化的地方很多,我推荐大家睡觉的时候听,老师主要时讲解代码,大家可以看一遍代码,然后就听就行了,我这样学习就是享受啊,因为我眼睛一...

含笑666
06/06
0
0
秒杀系统常见问题1

由于最近的面试老是遇到面试官问设计一个秒杀系统,当时也只是粗略的看了看,然后今天去陌陌面试又被问到了,被教育了一顿,然后晚上的笔试又让设计一个秒杀系统,我真是XXXXK,所以搜罗一波...

努力的C
2017/10/17
0
0
Web系统大规模并发:电商秒杀与抢购

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

天下杰论
2016/01/14
226
1

没有更多内容

加载失败,请刷新页面

加载更多

jenkins+docker+nodejs项目的自动部署环境

1、服务器安装docker yum install docker 2、jenkins安装 //创建jenkins工作目录mkdir -p /var/www/jenkins///拉取docker jenkins镜像docker pull jenkins //设置目前权限(必须...

西园里的猫
11分钟前
1
0
 索引和锁底层原理 !

索引和锁底层原理 ! 一、索引 在之前,我对索引有以下的认知: 索引可以加快数据库的检索速度; 表经常进行INSERT/UPDATE/DELETE操作就不要建立索引了,换言之:索引会降低插入、删除、修改...

DemonsI
20分钟前
0
0
转载:Java实现的SFTP

JSch - Java实现的SFTP(文件上传详解篇):https://www.cnblogs.com/longyg/archive/2012/06/25/2556576.html JSch - Java实现的SFTP(文件下载详解篇):https://www.cnblogs.com/longyg/......

WJtiny
23分钟前
0
0
聊聊storm的AssignmentDistributionService

序 本文主要研究一下storm的AssignmentDistributionService AssignmentDistributionService storm-2.0.0/storm-server/src/main/java/org/apache/storm/nimbus/AssignmentDistributionServic......

go4it
24分钟前
0
0
完全跨域的单点登录(SSO)解决方案源码解析

本文介绍的是一种PHP的开源SSO解决方案,可完全跨域,实现较简洁,源码地址:https://github.com/legalthings/sso 实现原理 一共分为3个角色: Client - 用户的浏览器 Broker - 用户访问的网...

庞陆阳
25分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部