秒杀场景分析和功能设计

秒杀场景分析和功能设计

脚本回顾

1.先登录到镜像仓库

2.从镜像仓库拉取镜像

3,判断主机中该镜像对象的容器是否启动

4.如果存在,先stop,再删除容器

5.如果容器没启动,直接run

架构图

  • nginx–反向代理、负载均衡

  • 网关0zuul

  • 微服务项目。。。order、web、user、product、kill、account

  • 注册中心eurka

  • 每个微服务模块,单独拎出来,都会有自己的数据库,用异步方式做了主从数据库

  • 中间件,mq用在高并发场景,kafaka做日志收集,redis、zookeeper做分布式锁

  • redis、mongodb做缓存

  • zipkin、es、es head、kafaka做日志收集

秒杀需求分析

  • 促销,吸引用户关注
  • 秒杀属于读多写少的场景
  • 秒杀流程一定要短

场景分析

  • 价格低廉
  • 大幅推广,量大
  • 瞬时售空
  • 定时上架
  • 瞬时并发高

技术挑战

  • 1.会对网站造成较大的冲击,如果和原有应用部署在一起,必然影响普通的业务,
    • 解决方案:将秒杀系统独立部署,甚至使用独立域名,使其与网站完全隔离。即物理隔离
  • 2.高并发下的应用、数据库负载在秒杀开始前,会不停狂刷界面以保证不过错过请求,会对应用服务器和数据库造成较大的负载压力。
    • 解决方案:重新设计一套单独的页面
  • 3.突然增加的网络和带宽,假设页面200k,那么需要的带宽是2g(200k x 10000),超过平时的带宽
    • 解决方案:重新购买或租借、将秒杀页面缓存在CDN,同样需要和CDN服务商临时租借新增的出口带宽
    • CDN:静态资源服务器加网络转发服务器
      • 1.加快界面响应速度,缓存静态页面
      • 2.各个地方的站点服务器(湖南、上海、北京、东京),有跨地域访问,此时访问速度是比较慢的,而CDN域名服务器会根据用户所在地解析到就近的CDN服务器,
      • 3.域名解析后会指向一个cdn服务器
      • 4.主要是为了静态资源加速,可以理解为一种就近缓存

秒杀的架构原则

  • 1.尽量将请求拦截在系统上游,传统项目之所以挂,请求都压到了后端数据层,读写锁冲突严重,并发响应慢,几乎所有的请求都在超时,流量虽大,但下单成功的流量很小,一趟火车有2000张票,200w个人来买,基本没有人能买成功,请求效率为0

    • 单体项目根本承受不了这么大的流量,网络连接数被耗光了
    • 数据库连接池也被打满了,同时上下文切换也很频繁,操作变慢,从而形成恶性循环
  • 2.读多写少的场景多使用缓存,这是一个读多写少的应用场景,上面那个案例写比例只有0.001,读占0.999。

秒杀架构设计

  • 1.为秒杀而生,更关心的是如何能快速刷新商品页面,在秒杀开始的时候抢先进入下单页面,尽量简化流程和每一步的操作,比如默认只能秒1个
  • 2.下单表单也尽可能简单,

前端设计

  • 1.静态界面加载js、css,
    • cdn节点
  • 2.点击秒杀后,按钮置灰
  • 3.js限制x秒内只能提交1次

拦截流量(大量的无效刷新)

秒杀站点设计

  • 1.nginx层针对同一iP的访问限流
  • 2.同一查询在站点层限制访问频率

这样又可以拦截99%流量在站点层(无效流量,恶意请求)

  • 高端程序员玩家手里掌握了10w台肉鸡服务器,在常用端口22、8080通过木马植入,来操控,这种秒杀跟普通用户基本没有区别了

  • 1.做验证码校验,验证是否是活人

  • 2.什么时候弹验证码,做同样的操作过多的时候

  • 3.可以提高秒杀的业务门槛,只允许星级用户可以参与秒杀,通过业务员手段限制

秒杀服务处设计

尽量不要把大量的请求瞬时落到数据库,会占满数据库的连接数,其他的用户只能傻傻的等待,就会超时,就会拖慢整个系统

  • 1.读请求,cache来扛,memcached,redis单机扛10w+应该没问题
  • 2.写请求,用队列,有并行转串行,

秒杀数据库设计

  • 主从架构,从的机器不要太多,cache已经起到了对数据库的一种弥补
  • 双主与级联复制结合架构
    • 真正的写只有一台
  • 主要去参照分库分表讲的数据架构

高并发要吞度量or系统保护

qps的计算

秒杀接口的设计指标为:5w/s的qps

例如秒杀系统有20台web服务器,maxclients为500,处理业务的平均响应时间为100ms

那么,web的理论峰值qps为

20*50 /0.1 = 100000 = 10w/s qps

这是绝对理论

maxclients的配置指标?

maxclients是web服务器配置的连接数,是一个线程数,但是并不是线程越多越好,为什么呢?

因为线程多了会增加cpu、内存的计算压力,线程切换时比较耗时的,线程的切换势必会增加用户的响应时间。所以web服务器的连接数要根据cpu、内存等硬件的实际情况来设置。

线程数量与吞度量

  • 不是线程数越高,你的单次请求速度和吞吐量就越高
  • 压测找到最合适的
  • 经验设计值,数据库连接数跟cpu的个数相关,一般是两倍再乘以一个因子

举例

  • 5w/s的并发怼过来,实例响应时间是250ms
  • 计算出qps = 20*500/0,25 = 40w/s
  • 还剩1w没办法处理,会出现请求拒绝的场景

过载保护机制

超过5w直接拒绝

系统安全的矛和盾

  1. 同一账号发送多次请求
    • redis
  2. 多个账号发送多次请求
    • 限制ip
  3. 多个账号,不同ip
    • 业务限制,星级用户,普通用户不能参加

  • 表名:tp_kill_goods_price 类名: KillGoodsContoller

detail - 查秒杀商品的详细信息

1.先从缓存里面查询数据

String killGoodsDetail = KillConstants.KILLGOOD_DATAIL + ID

KillGoodsSpecPriceDetailVo killGoodsSpecPriceDetailVo = redisTemplate.opsForValue).get()

2.去数据库里面查询数据

这是最常规的写法,可能发生缓存雪崩的问题,不同的接口涉及到的key同时失效—不同的key设置不一样的失效时间。

缓存雪崩----大量请求过来,直接怼数据库了

大量请求,请求不同的接口,不同的接口

  • 1.瞬时并发
  • 2.瞬时并发,接口涉及到的key,突然失效

解决方案

解决1:在下面查询数据库的方法里面加一个同步块

synchronized(iKillSpecManageService) {

​ 1.再查一次缓存(因为同步块的作用,t1的线程已经缓存了,t2可以直接走缓存了)

​ 2.去数据库里面查询数据

}

解决方法1的补充,做缓存预热,使程序更健壮:

缓存里面一般这种比较热的数据,秒杀商品这种,缓存里面一定要有,启动项目的时候,就必须要把热门数据做缓存预热,

©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页