秒杀设计
系统数据流
前端浏览器秒杀页面->中间代理服务->后端服务->数据库
整体思路
限流:屏蔽掉无用的流量,允许少部分流量流向后端。
削峰:瞬时大流量峰值容易压垮系统,解决这个问题是重中之重。常用的消峰方法有异步处理、缓存和消息中间件等技术。
异步处理:秒杀系统是一个高并发系统,采用异步处理模式可以极大地提高系统并发量,其实异步处理就是削峰的一种实现方式。
内存缓存:秒杀系统最大的瓶颈一般都是数据库读写,由于数据库读写属于磁盘IO,性能很低,如果能够把部分数据或业务逻辑转移到内存缓存,效率会有极大地提升。
可拓展:当然如果我们想支持更多用户,更大的并发,最好就将系统设计成弹性可拓展的,如果流量来了,拓展机器就好了。像淘宝、京东等双十一活动时会增加大量机器应对交易高峰。
消息队列:消息队列可以削峰,将拦截大量并发请求,这也是一个异步处理过程,后台业务根据自己的处理能力,从消息队列中主动的拉取请求消息进行业务处理。
充分利用缓存:利用缓存可极大提高系统读写速度。
具体方案
前端方案:
静态资源缓存,将活动页面上的所有可以静态的元素全部静态化,尽量减少动态元素;通过CDN缓存静态资源,来抗峰值。
禁止重复提交,用户提交之后按钮置灰,禁止重复提交。
用户限流,在某一时间段内只允许用户提交一次请求,比如可以采取IP限流
秒杀开始时间同步,防止提前下单,
利用验证码,防止恶意刷单
中间代理层:
负载均衡,(例如反响代理Nginx等)使用多个服务器并发处理请求,减小服务器压力
服务层:
使用网关,限制同一UserID访问频率,尽量拦截浏览器请求,但针对某些恶意攻击或其它插件,在服务端控制层需要针对同一个访问uid,限制访问频率
分布式设计,拆分秒杀业务,可独立动态扩展
采用异步事件流,将同步的业务,设计成异步处理的任务,提高网站的整体可用性
采用消息队列缓存请求,将大流量请求写到消息队列缓存,利用服务器根据自己的处理能力主动到消息缓存队列中抓取任务处理请求,数据库层订阅消息减库存,减库存成功的请求返回秒杀成功,失败的返回秒杀结束
利用缓存应对读请求:对于读多写少业务,大部分请求是查询请求,所以可以读写分离,利用缓存分担数据库压力
利用缓存应对写请求:缓存也是可以应对写请求的,可把数据库中的库存数据转移到Redis缓存中,所有减库存操作都在Redis中进行,然后再通过后台进程把Redis中的用户秒杀请求同步到数据库中。
其他策略
消息队列缓存请求,按照队列模型取任务执行,秒杀完毕即终止到秒杀结束页面
使用数组为并发请求随机分配秒杀状态(成功和失败),然后将分配到失败状态的请求派发到秒杀失败的页面,分到成功状态的用户在慢慢的按顺序执行秒杀操作;(如果处理失败了可以利用日志来查找具体秒杀失败的商品和用户,执行补救措施或者从其他用户中拿取一个来执行秒杀操作)
用数组为用户分配秒杀资格,将大流量的用户限制为小流量的用户,得到秒杀资格的去执行秒杀,得不到秒杀资格的跳到秒杀失败页面