如何设计一个秒杀系统

如何设计一个秒杀系统

标签: 秒杀系统秒杀架构秒杀高并发前端

2016-09-21 14:23 3121人阅读 评论(1) 收藏 举报mysql

 分类:redis

框架(1) sql

版权声明:本文为博主原创文章,未经博主容许不得转载。数据库

目录(?)[+]后端

什么是秒杀

秒杀场景通常会在电商网站举行一些活动或者节假日在12306网站上抢票时遇到。对于电商网站中一些稀缺或者特价商品,电商网站通常会在约定时间点对其进行限量销售,由于这些商品的特殊性,会吸引大量用户前来抢购,而且会在约定的时间点同时在秒杀页面进行抢购。浏览器

秒杀系统场景特色

  • 秒杀时大量用户会在同一时间同时进行抢购,网站瞬时访问流量激增。
  • 秒杀通常是访问请求数量远远大于库存数量,只有少部分用户可以秒杀成功。
  • 秒杀业务流程比较简单,通常就是下订单减库存。

秒杀架构设计理念

限流: 鉴于只有少部分用户可以秒杀成功,因此要限制大部分流量,只容许少部分流量进入服务后端。缓存

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

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

内存缓存:秒杀系统最大的瓶颈通常都是数据库读写,因为数据库读写属于磁盘IO,性能很低,若是可以把部分数据或业务逻辑转移到内存缓存,效率会有极大地提高。

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

架构方案

通常秒杀系统架构

这里写图片描述

设计思路

将请求拦截在系统上游,下降下游压力:秒杀系统特色是并发量极大,但实际秒杀成功的请求数量却不多,因此若是不在前端拦截极可能形成数据库读写锁冲突,甚至致使死锁,最终请求超时。 
充分利用缓存:利用缓存可极大提升系统读写速度。 
消息队列:消息队列能够削峰,将拦截大量并发请求,这也是一个异步处理过程,后台业务根据本身的处理能力,从消息队列中主动的拉取请求消息进行业务处理。

前端方案

浏览器端(js):

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

后端方案

服务端控制器层(网关层)

限制uid(UserID)访问频率:咱们上面拦截了浏览器访问的请求,但针对某些恶意攻击或其它插件,在服务端控制层须要针对同一个访问uid,限制访问频率。

服务层

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

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

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

  3. 利用缓存应对写请求:缓存也是能够应对写请求的,好比咱们就能够把数据库中的库存数据转移到Redis缓存中,全部减库存操做都在Redis中进行,而后再经过后台进程把Redis中的用户秒杀请求同步到数据库中。

数据库层

数据库层是最脆弱的一层,通常在应用设计时在上游就须要把请求拦截掉,数据库层只承担“能力范围内”的访问请求。因此,上面经过在服务层引入队列和缓存,让最底层的数据库高枕无忧。

案例:利用消息中间件和缓存实现简单的秒杀系统

Redis是一个分布式缓存系统,支持多种数据结构,咱们能够利用redis轻松实现一个强大的秒杀系统。

咱们能够采用Redis 最简单的key-value数据结构,用一个原子类型的变量值(AtomicInteger)做为key,把用户id做为value,库存数量即是原子变量的最大值。对于每一个用户的秒杀,咱们使用 RPUSH key value插入秒杀请求, 当插入的秒杀请求数达到上限时,中止全部后续插入。

而后咱们能够在台启动多个工做线程,使用 LPOP key 读取秒杀成功者的用户id,而后再操做数据库作最终的下订单减库存操做。

固然,上面Redis也能够替换成消息中间件如ActiveMQRabbitMQ等,也能够将缓存和消息中间件 组合起来,缓存系统负责接收记录用户请求,消息中间件负责将缓存中的请求同步到数据库。

相关文章
相关标签/搜索