高并发秒杀系统设计

高并发秒杀系统设计

功能模块划分-》秒杀策略-》自己的优化点-》工具测试抗压-》

一.秒杀系统特点

1.秒杀业务简单,卖家查询,买家下订单减库存
2.秒杀时网站访问流量激增,出现峰值
3.访问请求数量远大于实际需求量

二.架构设计优化方案

1.秒杀系统架构设计优化

一个常规的秒杀系统从前到后,依次有:
	前端浏览器秒杀页面-》中间代理服务-》后端服务层-》数据库层

根据这个流程,一般优化设计思路:将请求拦截在系统上游,降低下游压力。在一个并发量大
实际需求小的系统中,应当尽量在前端拦截无效流量,降低下游服务器和数据库的压力,不然很可能造成数据库读写锁冲突,甚至导致死锁,最终请求超时。
整体设计思路和优化点:
限流:屏蔽掉无用的流量,允许少部分流量流向后端。
削峰:瞬时大流量峰值容易压垮系统,解决这个是重中之重。常用的削峰方法有异步处理,缓存和中间件技术。
异步处理:秒杀系统是一个高并发系统,采用异步处理模式可以极大提高系统并发量,其实异步处理是削峰的一种实现方式。
内存缓存:秒杀系统最大的瓶颈一般都是数据库读写,由于数据库读写属于磁盘IO,性能很低,如果能够把部分数据或业务逻辑转移到内存缓存,效率会极大提升。
可扩展:当然如果我们想支持更多用户,更大的并发,最好就将系统设计成弹性可扩展的,如果流量来了,扩展机器就好了。像淘宝,京东双十一活动时会增加大量的机器应对交易高峰。
消息队列:消息队列可以削峰,将拦截大量并发请求,这也是一个异步处理过程,后台业务根据自己的处理能力,从消息队列中主动的拉取请求消息进行业务处理。
充分利用缓存:利用缓存可极大提高系统读写速度。

2.详细方案
前端方案:
静态资源缓存:将活动页面上的所有可以静态地元素全部静态化,尽量减少动态元素;通过CDN缓存静态资源,来抗峰值。
禁止重复提交:用户提交之后按钮置灰,禁止重复提交。
用户限流:在某一时间段内只允许用户提交一次请求,比如可以采取IP限流。
中间代理层:
可利用负载均衡(如反向代理Nginx)使用多个服务器并发处理请求,减少服务器压力。
后端方案:
控制层
限制同一UserId访问频率:尽量拦截浏览器请求,但针对某些恶意攻击或其他插件,在服务端控制层需要针对同一个访问uid,限制访问频率。
服务层
当用户量非常大时,拦截流量后的请求访问量还是非常大,此时仍需进一步优化。
(1)业务分离:将秒杀业务系统和其他业务分离,单独放在高配服务器上,可以集中资源对访问请求抗压。
(2)采用消息队列缓存请求:将大流量请求写到消息队列缓存,利用服务器根据自己的处理能力,主动到消息缓存队列中抓取任务处理请求,数据库层订阅消息减库存,数据库层订阅消息减库存,减库存成功的请求返回秒杀成功,失败的返回秒杀结束。
(3)利用缓存应对读请求:对于读多写少业务,大部分请求是查询请求,所以可以读写分离,利用缓存分担数据库压力。
(4)利用缓存应对写请求:缓存也是可以应对写请求的,可把数据库中的库存数据转移到Redis缓存中,所有减库存操作都在Redis中进行,然后再通过后台进程把Redis中的用户秒杀请求同步到数据库中。
数据库层
数据库层是最脆弱的一层,一般在应用设计时在上游就需要把请求拦截掉,数据库层只承担“能力范围内”的访问请求。所以,上面通过在服务器引入队列和缓存,让最底层的数据库高枕无忧。
如果不适用缓存来作为中间缓存而是直接访问数据库的话,可以对数据库进行优化,减少数据库压力。
对于秒杀系统,直接访问数据库的话,存在一个事务竞争优化问题,可使用存储过程等技术绑定操作,整个事务在MySql端完成,把整个热点执行放在一个过程当中一次性完成,可以屏蔽掉网络延迟时间,减少行级锁持有时间,提高事务并发访问速度。
其他秒杀策略
减少硬件开销的策略:
策略1:消息队列缓存请求,按照队列模型取任务执行,秒杀完毕即终止到秒杀结束页面。
策略2:使用数组为并发请求随机分配秒杀状态(成功和失败),然后将分派到失败状态的请求派发到秒杀失败页面,分到成功状态的用户在慢慢的的按顺序执行秒杀操作。
策略3:用数组为用户分配秒杀资格,将大流量的用户限制为小流量的用户,得到秒杀资格的去执行秒杀,得不到秒杀资格的跳到秒杀失败页面。分配秒杀资格的策略(数组状态密度不同,由前到后逐渐稀疏,可以让先到的在前面随机分配,后到的在后面随机分配,根据先到的时间)

三.案例:利用消息中间件和Redis缓存实现

Redis是一个分布式缓存系统,支持多种数据结构,可以用Redis轻松实现一个强大的秒杀系统。我们可以利用最简单的key-value数据结构,用一个原子类型的变量值作为key,把用户Id作为value,库存数量便是原子变量的最大值。对于每个用户的秒杀,我们使用RPUSH key value插入秒杀请求,当插入的秒杀请求数达到上限时,停止所有后续插入。然后我们可以再启动多个工作线程,使用LPOP key读取秒杀成功者的用户Id,然后再操作数据库做最终的下订单减库存操作。上面的Redis也可以替换成消息中间件如ActiveMQ,RabbitMQ等,也可以将缓存和消息中间件组合起来,缓存系统负责接收记录用户请求,消息中间件负责将缓存中的请求同步到数据库。
(1)使用Redis中间件缓存动态资源的好处?
提高访问速度,减少对数据库的连接的打开和关闭。
(2)为什么不用JVM内存而使用Redis作为缓存?
JVM内存较小,隔一段时间会自动进行垃圾回收。
JVM和业务程序绑定在一起了,如果程序出错,JVM也会停止,这样就导致缓存数据丢失。

压力测试

使用JMeter压测工具
下载,安装,进入C:/JMeter/bin下面的jmeter.bat批处理文件来启动Jmeter的可视化界面,进入测试计划添加线程组,设置线程数,循环次数,添加Http默认请求,服务器名称,IP,以及自己设定的携带参数
添加监听器,存放测试结果,聚合报告,可以表格查询,图形结果,数结果。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值