秒杀场景高并发解决方案

<!--[if !supportLists]-->1.         <!--[endif]-->秒杀架构设计理念:

限流: 鉴于只有少部分用户能够秒杀成功,所以要限制大部分流量,只允许少部分流量进入服务后端。

削峰:对于秒杀系统瞬时会有大量用户涌入,所以在抢购一开始会有很高的瞬间峰值。高峰值流量是压垮系统很重要的原因,所以如何把瞬间的高流量变成一段时间平稳的流量也是设计秒杀系统很重要的思路。实现削峰的常用的方法有利用缓存和消息中间件等技术。

异步处理:秒杀系统是一个高并发系统,采用异步处理模式可以极大地提高系统并发量,其实异步处理就是削峰的一种实现方式。

内存缓存:秒杀系统最大的瓶颈一般都是数据库读写,由于数据库读写属于磁盘IO,性能很低,如果能够把部分数据或业务逻辑转移到内存缓存,效率会有极大地提升。

可拓展:当然如果我们想支持更多用户,更大的并发,最好就将系统设计成弹性可拓展的,如果流量来了,拓展机器就好了。像淘宝、京东等双十一活动时会增加大量机器应对交易高峰。

 

<!--[if !supportLists]-->2.         <!--[endif]-->具体实现方案:

2.1 前端部分:

浏览器端(js):

页面静态化:将活动页面上的所有可以静态的元素全部静态化,并尽量减少动态元素,通过CDN来抗峰值。 
禁止重复提交:用户提交之后按钮置灰,禁止重复提交。
用户限流:在某一时间段内只允许用户提交一次请求,比如可以采取IP限流。

 

2.2 后端方案

上面只拦截了一部分访问请求,当秒杀的用户量很大时,即使每个用户只有一个请求,到服务层的请求数量还是很大。比如我们有100W用户同时抢100台手机,服务层并发请求压力至少为100W。

1.采用消息队列缓存请求:既然服务层知道库存只有100台手机,那完全没有必要把100W个请求都传递到数据库啊,那么可以先把这些请求都写到消息队列缓存一下,数据库层订阅消息减库存,减库存成功的请求返回秒杀成功,失败的返回秒杀结束。

2.利用缓存应对读请求:对类似于12306等购票业务,是典型的读多写少业务,大部分请求是查询请求,所以可以利用缓存分担数据库压力。

3.利用缓存应对写请求:缓存也是可以应对写请求的,比如我们就可以把数据库中的库存数据转移到Redis缓存中,所有减库存操作都在Redis中进行,然后再通过后台进程把Redis中的用户秒杀请求同步到数据库中。

 

具体后端实现方案一:

可以使用redis分布式缓存来实现一个高并发秒杀服务。

使用并发包下的原子类AtomicInteger的值作为key,用户ID作为value。

使用redis的list数据类型,使用rpush操作,将后请求的用户ID放到list的末尾,当达到秒杀资源的上限时,停止插入list,直接返回。

然后将list里的元素使用lpop操作,将其作为秒杀成功的用户,然后异步进行扣减库存,生成订单等操作。

 

后端具体实现方案二:

使用消息队列方式,将请求的用户ID放入队列,然后异步消费。

 

 

相关推荐