赞
踩
将请求尽量拦截在系统上游,同时对请求进行限流和削峰。大体架构如下
限流:前端答题或验证码,来分散用户的请求
禁止重复提交:限定每个用户发起一次秒杀后,需等待才可以发起另一次请求,从而减少用户的重复请求
本地标记:用户成功秒杀到商品后,将提交按钮置灰,禁止用户再次提交请求
动静分离:将前端静态数据直接缓存到离用户最近的地方,比如用户浏览器、CDN 或者服务端的缓存中
限流:屏蔽掉无用的流量,允许少部分流量走后端。假设现在库存为 10,有 1000 个购买请求,最终只有 10 个可以成功,99% 的请求都是无效请求。
削峰:秒杀请求在时间上高度集中于某一个时间点,瞬时流量容易压垮系统,因此需要对流量进行削峰处理,缓冲瞬时流量,尽量让服务器对资源进行平缓处理
异步:将同步请求转换为异步请求,来提高并发量,本质也是削峰处理
利用缓存:创建订单时,每次都需要先查询判断库存,只有少部分成功的请求才会创建订单,因此可以将商品信息放在缓存中,减少数据库查询。
负载均衡:利用 Nginx 等使用多个服务器并发处理请求,减少单个服务器压力
服务端的优化
悲观锁虽然可以解决超卖问题,但是加锁的时间可能会很长,会长时间的限制其他用户的访问,导致很多请求等待锁,卡死在这里,如果这种请求很多就会耗尽连接,系统出现异常。乐观锁默认不加锁,更新失败就直接返回抢购失败,可以承受较高并发
详细的限流算法可以采用令牌桶:
令牌桶算法的流程:
3. Redis 缓存商品库存信息
虽然限流能够过滤掉一些无效的请求,但是还是会有很多请求落在数据库上,实时查询库存的语句被大量调用,对于每个没有被过滤掉的请求,都会去数据库查询库存来判断库存是否充足,对于这个查询可以放在缓存 Redis 中,Redis 的数据是存放在内存中的,速度快很多。
缓存预热
在秒杀开始前,需要将秒杀商品信息提前缓存到 Redis 中,这么秒杀开始时则直接从 Redis 中读取,也就是缓存预热,Springboot 中开发者通过 implement ApplicationRunner 来设定 SpringBoot 启动后立即执行的方法.
缓存和数据一致性
缓存和 DB 的一致性是一个讨论很多的问题,推荐看参考本人的另一篇博客,可以采用简单的cache aside 策略即先把数据存到数据库中,成功后,再去删除缓存或者让缓存失效。也可以使用乐观锁来进行数据库的库存修改
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。