一次阿里面试,我被问到了如何设计秒杀系统

开发 架构
秒杀活动是电商项目中常出现的活动。比如演唱会门票抢购,京东淘宝秒杀商品抢购。在抢购那一刻,会有大量用户同时高并发的请求应用系统,可能会达到每秒几万、几十万的请求。如果系统无法处理这么高的请求,那么就会崩溃,从而导致系统不可用。

秒杀活动架构

秒杀活动是电商项目中常出现的活动。比如演唱会门票抢购,京东淘宝秒杀商品抢购。在抢购那一刻,会有大量用户同时高并发的请求应用系统,可能会达到每秒几万、几十万的请求。如果系统无法处理这么高的请求,那么就会崩溃,从而导致系统不可用。

对于秒杀活动来说,要求系统不会出现压力过大而崩溃的场景,并且不会出现超卖、少卖的情形。

所以秒杀系统中我们需要思考:

  • “系统如何扛住高并发请求系统如何保证不超卖等问题”

对此我的解决思路是:

  • “服务端中,使用缓存减少对数据库访问将请求流量拦截在上游,可以使用限流技术使用分布式队列进行流量削峰,将并发串行化”

 

一次阿里面试,我被问到了如何设计秒杀系统
秒杀架构图

秒杀架构图如上。

客户端

用户发起请求的端口,目前电商项目秒杀活动主要客户端有微信小程序、H5(浏览器)、各平台app(比如Android、iOS、Windows)。我们可以在客户端实现限流机制,这样就可以避免用户发送大量请求到服务端。

客户端的限流可以控制按钮的点击频率,比如对按钮置灰。

反向代理

我们可以使用Nginx实现请求分流,通过负载均衡将请求均匀的分布到不同的Web节点中。

Nginx也可以作为限流使用。Nginx可以控制单位时间内的请求数,限制同一时间的连接数。

API网关

如果实际参与秒杀活动的用户非常大,并发请求非常大。我们就需要在API网关这一层中进行限流,这里可以实现对单个Web节点实现每秒最大请求数限制。

我们也可以控制每个用户的最大请求数,通过Redis记录每个用户的请求数。

缓存

在服务层业务中,为减少对数据库的访问,需要进行缓存设计,我们可以使用本地缓存,或者分布式缓存。

队列

队列主要是用来实现流量的削峰填谷,我们可以使用RocketMQ、Kafka等消息中间件作为分布式的队列。

关于限流

秒杀系统中为什么需要限流?在秒杀活动中商品库存是有限的,而请求的用户数量远远大于商品库存数量。大部分的用户请求实际上是无法抢到商品的无效流量。所以这部分流量可以拦截在上游进行限流。

为了避免用户采用脚本或者频繁点击发送大量请求,而导致其他用户无法正常参加活动,我们也需要控制用户每秒的请求量。

我们可从URI和用户两个方面实行限流。

URI限流示例代码:

 

一次阿里面试,我被问到了如何设计秒杀系统

用户维度的限流示例代码:

 

一次阿里面试,我被问到了如何设计秒杀系统

我们获取URI维度的限流器对象uriLimiter,和用户维度的限流器对象userLimiter。如果tryAcquire()成功获得许可,则请求通过,进入后续业务。否则直接报异常,前端界面作相应的友好提示。

在缓存中扣减库存

使用Redis来存储库存数量,当用户发起抢购请求时,先判断Redis中的库存是否可用。如果可用,将抢购请求放入分布式队列中,采用异步方式处理后续操作,并完成下单。同时在Redis中作库存扣减。

示例代码如下:

 

一次阿里面试,我被问到了如何设计秒杀系统

先做库存扣减并获取扣减后的库存数量,如果库存数量大于或等于0,将订单创建请求发送到mq。否则返回抢购失败的信息。

消费者创建订单:

 

一次阿里面试,我被问到了如何设计秒杀系统

关于如何初始化库存?

在抢购活动开始前,有运营人员在后台手动将商品库存从数据库同步到缓存中。库存的扣减在缓存中进行扣减。

利用Redis单线程特性可以实现多线程下安全的库存更新。如果查询缓存中的值时,发现没有,需要从数据库中查询,然后再同步到缓存中,这个过程需要加锁。

示例代码如下:

 

一次阿里面试,我被问到了如何设计秒杀系统

总结

秒杀设计是典型的高并发系统,关于秒杀系统的设计,经常会在面试中被问到。在设计秒杀系统时,我们需要考虑:

  • “请求分流-通过负载均衡实现限流-采用漏斗算法(如guava的RateLimiter),信号量Semaphore,Redis计数等实现Redis扣减库存-减少对数据库的访问流量削峰-分布式队列实现”

 

责任编辑:未丽燕 来源: 今日头条
相关推荐

2020-07-08 07:44:35

面试阿里加班

2019-09-12 09:40:34

秒杀系统高并发

2020-08-13 10:15:34

MySQL数据库面试

2018-03-05 17:32:06

开发者编程面试

2019-05-28 11:49:09

2020-04-30 10:24:35

Spring循环依赖Java

2019-10-31 13:58:32

阿里电商系统

2012-07-12 14:35:31

面试经历

2019-11-14 09:32:16

程序员MySQLRedis

2014-08-01 14:06:45

2020-03-10 07:51:35

面试讽刺标准

2018-08-15 10:33:03

阿里巴巴面试JAVA

2020-04-08 10:30:19

Linux 攻击 安全

2019-12-09 10:37:27

Hash算法面试

2019-05-25 14:17:51

面试阿里社招

2019-12-03 14:09:49

阿里面试HR

2017-01-23 12:40:45

设计演讲报表数据

2024-04-28 08:52:33

RabbitMQ延迟队列延迟插件

2021-03-10 08:47:46

反射Java对象

2022-07-18 08:02:16

秒杀系统后端
点赞
收藏

51CTO技术栈公众号